Axios refresh token issue

199 views Asked by At

I'm using React.useEffect() to retrieve the users list.

React.useEffect(() => {
dispatch(UsersActions.creators.fetchingUsersAction());
UsersApi.methods.getUsers().then(
  (res) => {
    dispatch(UsersActions.creators.fetchUsersSuccessAction(res.data));
  },
  (e) => {
    dispatch(UsersActions.creators.fetchUsersErrorAction());
  }
);
}, [dispatch]);

On this example, fetchingUsersAction is used to set "loading" to true, and fetchUsersErrorAction to false. This works fine, except when the request fails due to token expiration.

ApiClient.interceptors.response.use(
  function (response) {
    return response;
  },
  function (error) {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      const refresh = JSON.stringify({
        refreshToken: localStorage.getItem("refresh"),
      });
      AuthenticationApi.methods.refresh(refresh).then((res) => {
        if (res.data.accessToken) {
          localStorage.setItem("token", res.data.accessToken);
        }
        ApiClient.defaults.headers.common["Authorization"] =
          "Bearer " + res.data.accessToken;
        originalRequest.headers["Authorization"] =
          "Bearer " + res.data.accessToken;
        return ApiClient(originalRequest);
      });
    }
    return Promise.reject(error);
  }
);

This is sending a request to generate a new token and the previous request, but since the first request failed, the useEffect is going to the error section, making the "loading" false and showing the users list based on the previous state. What is the best way to deal with this problem?

Thanks

1

There are 1 answers

0
Victor Hugo Correa Cid On

You should create an Async fucntion inside useEffect hook and use await to wait for the response, then call the function. Here is one example:

  useEffect(() => {
    const getRoles = async () => {
      await authService.roles().then((res) => {
        //Do your stuff.
        console.log(res);
      }).catch((error) => {
        console.log(`'Catching the error: '${error}`);
      });
    };
    //Call the recent created function.
    getRoles();
  }, []);

Your interceptor looks good to me.