import jwt_decode from "jwt-decode"; import { useEffect, useRef } from "react"; interface AppToken { exp?: number; iat?: number; } const TIME_BEFORE_REFRESH = 30 * 1000; // 30 seconds const useTokenRefresh = (token?: string, refetch?: () => void) => { let decoded: AppToken = { exp: 0, iat: 0, }; // For some reason jwt_decode causes seemingly unrelated error in tests // It seems like at some point undefined token is passed // Wrapping it in try..catch and if fixes the issue try { if (token) { decoded = jwt_decode(token) as AppToken; } } catch (e) { console.warn(e); } const decodedSuccesfully = !!decoded?.iat && !!decoded?.exp; const refreshTimeout = useRef>(null); const tokenLife = ((decoded?.exp || 0) - (decoded?.iat || 0)) * 1000; // in ms const refreshTime = tokenLife - TIME_BEFORE_REFRESH; const setUpTimeout = () => { if (refetch) { refetch(); } createTimeout(); }; const createTimeout = () => { refreshTimeout.current = setTimeout(setUpTimeout, refreshTime); }; const deleteTimeout = () => { if (refreshTimeout?.current) { clearTimeout(refreshTimeout.current); refreshTimeout.current = null; } }; useEffect(() => { if (refetch && decodedSuccesfully) { createTimeout(); } return () => { if (!!refetch && decodedSuccesfully) { deleteTimeout(); } }; }, [token]); }; export default useTokenRefresh;