在React Js axios拦截器中使用钩子,同时刷新令牌

fafcakar  于 9个月前  发布在  iOS
关注(0)|答案(1)|浏览(119)

在我的React JS(Vite + TS)应用程序中,我使用https://stackoverflow.com/a/53256982/22404569中的Used解决方案来刷新令牌,BE将httpOnly cookie作为access_tokes发送,因此需要FE来处理令牌。

问题:我想在“/tokens-renew”API失败时将用户重定向到/login
我的方法我尝试使用handelLogout()来实现。这种方法无法实现,因为钩子只能在函数组件内部调用。

我相信handelLogout()是至关重要的,因为它管理所有有助于保持私有路由的标志。

请注意刷新令牌和重试API是完美的工作,卡住的情况下401 /tokens-renew和我想重定向用户.

export const handleLogout = () => {
    const dispatch = useDispatch();
    const showToast = useToast();
    const navigate = useNavigate();
    // Clear the local storage and dispatch the signOut action to update the Login flag to false
    localStorage.clear();
    dispatch(signOut()); // Dispatch the action to sign out the user (e.g., clear authentication state in Redux)
    navigate("/login"); // Navigate to the login page 
    showToast("Session expired.", EToastTypes.WARNING); //A custom Hook for Toast msg
};
let isTokenRenewing = false;

...

axios.interceptors.response.use(
    res => res,
    async (err) => {
        // In case of token expire 
        if (err.response.status === 401 && !isTokenRenewing)//Cheks if any API has 401 and there was no req made prior to this 
        {
            isTokenRenewing = true;
            let url = import.meta.env.VITE_API_BASEURL + '/tokens-renew';
            try {
                const response = await axios.get(url);
                if (response.status === 200) {
                    return axios(err.config)
                }
            }
            catch (err) {
                // For case request /tokens-renew got 401 
                // handleLogout()
            }
        }
        // For case request was already made and got 401 
        else {
            // handleLogout()
        }

        return Promise.reject(err);
    }
);
fv2wmkja

fv2wmkja1#

你考虑过在Axios拦截器外处理401吗?
我认为你可以使用一个自定义钩子(https://react.dev/learn/reusing-logic-with-custom-hooks),在那里你调用“/tokens-renew”,并处理该响应。
它看起来像这样:

export function useIsLoggedIn() {
  const dispatch = useDispatch();
  const showToast = useToast();
  const navigate = useNavigate();
  const apiResponse = service.callAPI(); // Here you'd call tokens-renew

  if(apiRespose.response.status === 401) {
    localStorage.clear();
    dispatch(signOut()); 
    navigate("/login"); 
    showToast("Session expired.", EToastTypes.WARNING);
  }
}

然后你可以在任何需要的地方使用这个钩子,如果你想定期调用这个API,你也可以用一个useEffect钩子来 Package 这个API调用。

相关问题