How to save and then later delete timeoutId in React inside a async thunk that is dispatched

96 Views Asked by At

I have a problem that I don't know how to fix.

I want to call refresh-token endpoint when setTimeout time runs out. setTimeout is called in 2 different ways:

  1. When user logs in
  2. When user enters a page again and has bearer token

If I just called setTimeout without deleting the previous one, a user could log in and out and log in again and it would send a request to the refresh-token endpoint for every setTimeout that was created (in this case, 2 requests).

What I want to do is save the setTimeout that was created and if user decides to log out and then log in again, we delete setTimeout and create a new one. However, when I store my timeoutId with useState, I get Invalid hook call error.

This is how my code looks like:

storageActions.ts

export function setRefreshTokenTimeout(bearerToken: string, refreshToken: string) {
removeRefreshTokenTimeout();

var decodedBearerToken: any = jwt_decode(bearerToken);

let remainingDuration = calculateRemainingTime(decodedBearerToken.exp * 1000);
remainingDuration = 10000;

const refreshTokens = setTimeout(() => store.dispatch(refreshTokensThunk({ refreshToken })), remainingDuration);
setRefreshTokensTimeout(refreshTokens);
}

export function removeRefreshTokenTimeout() {
    if (refreshTokensTimeout) {
        clearTimeout(refreshTokensTimeout);
        setRefreshTokensTimeout(undefined);
    }
}

authActions.ts

export const userLoginThunk = createAsyncThunk<UserLoginResponse, UserLoginRequest>(
"auth/user-login",
async (request, thunkAPI) => {
    let response = await AuthServiceUserLogin(request);
    setUserLocalStorageData(response.data);
    setRefreshTokenTimeout(response.data.bearerToken, response.data.refreshToken);
    return response.data;
    }
);

export const authUserThunk = createAsyncThunk("auth/authUser", async thunkAPI => {
    await AuthServiceAuthUser();
    const userStorage = getUserLocalStorageData();
    if (userStorage?.data?.bearerToken) {
        setRefreshTokenTimeout(userStorage.data.bearerToken, userStorage.data.refreshToken);
    }
});

All of these are called inside a createAsyncThunk that is dispatched. Is there any way to solve this problem?

1

There are 1 best solutions below

0
Ivan Kralj On

I knew this was because of useState hook, but I thought that you can only save states with hooks like useState or useRef.

I just figured out that this rule only refers to React components. storageActions.ts isn't a component, therefore I can use a simple variable to save my timeoutId.

I tested it and it works.