How to utilize refresh tokens in React SPA?

I’m trying tot make use of refresh tokens in my React SPA. I’ve set things up with localstorage and offline_access to do so. Previously, I would use the below code to call logout() when the timer sees expiration time was hit, but I was hoping to use refresh tokens. I thought getTokenSilently() would do that, but it doesn’t seem to – the token variable stays the same. What am I missing?

  // Continually check for login expiration
  useEffect(() => {
    async function refreshToken() {
      const isAuthenticated = await auth0Client.isAuthenticated();
      const token = await auth0Client.getTokenSilently();

      if (isAuthenticated) {
        const claims = await auth0Client.getIdTokenClaims();
        const claimsDecoded = await jwt_decode(claims.__raw);

        dispatch({
          type: 'REFRESH_TOKEN',
          payload: {
            user: {
              token: token,
              expires: claimsDecoded.exp,
              claims: claims.__raw
            }
          }
        });
      } else {
        logout();
      }
    };

    const delay = 20000;
    const timer = setInterval(() => {
      console.log(':: expiration check');
      let currentDtm = Math.round((new Date()).getTime() / 1000);
      if (state.user) {
        const expDtm = state.user.expires;

        if (currentDtm >= expDtm) {
          console.log(':: SESSION EXPIRED');
          clearInterval(timer);
          //logout();
          refreshToken();
        }
      } else {
        clearInterval(timer);
      }
    }, delay);
    return () => clearInterval(timer);
  }, [state.isAuthenticated, state.user]);

I should also note that I send the claims attribute as the Bearer token to the API. Does the token within the claims get renewed as well?

Update: I think the issue here is that when issuing getTokenSilently(), a subsequent call to getIdTokenClaims() does not contain the updated token. However, I send the entire claims/JWT to the API I’m calling. Is that expected behavior? Any way to get the updated token in the claims as well?

First if all, why do you check the token continuously?
I recommend intercepting XHRs and checking it there. That why you are not continuously checking it and not getting in the risk of unessential rerenders.
Axios can intercept the requests like a middleware does.

I’m merely checking the token expiration based on current time, then renewing when that gets hit. I could also renew when the API throws a 401, but I’m trying this for now. Even so, renewing the token does not seem to renew what’s in the claims.

I’ve done something more sensible (still testing) and instead use setTimeout() call to expire the session when the set amount of time elapses. Still, I imagine the issue with the claims not being updated will remain:

    const currentDtm = Math.round((new Date()).getTime());

    const timer = setTimeout(() => {
      if (state.user?.expires) {
        console.log(':: SESSION EXPIRED');
        clearTimeout(timer);
        refreshToken();
      } else {
        clearTimeout(timer);
      }
    }, (state.user?.expires * 1000) - currentDtm);