You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router 6会话过期时,触发事件后跳转落地页的实现方案

解决方案

要解决会话过期后未刷新页面触发事件无响应的问题,核心是全局拦截API请求错误并统一处理跳转,同时优化权限校验逻辑,确保任何操作触发的会话过期都能被捕获。

1. 全局Axios拦截器统一处理401错误

所有API请求都通过封装的Axios实例发起,拦截响应中的401(会话过期/未授权)状态,直接清除本地状态并跳转落地页。

import axios from 'axios';
import { store } from './store'; // 你的Redux Store
import { LOGOUT_USER } from './actionTypes'; // 清除用户状态的action类型

// 创建带配置的Axios实例
const api = axios.create({
  baseURL: BASE_URL,
  withCredentials: true
});

// 响应拦截器:捕获会话过期错误
api.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) {
      // 清除本地存储和Redux用户状态
      localStorage.removeItem('id');
      store.dispatch({ type: LOGOUT_USER });
      // 跳转落地页(直接用location.href避免组件外无法调用useNavigate的问题)
      window.location.href = '/landingPage';
    }
    return Promise.reject(error);
  }
);

export default api;

2. 优化用户状态校验逻辑

用Redux中的用户状态替代localStorage判断权限,避免本地存储不一致导致的校验失效。

修正getCurrentUser Action

import api from './api'; // 使用上面封装的Axios实例

export const getCurrentUser = () => async (dispatch) => {
    try {
        const res = await api.get(GET_CURRENT_USER);
        localStorage.setItem('id', res.data.id);
        dispatch({
            type: GET_CURRENT_USER,
            payload: res.data
        });
        return res.data;
    } catch (err) {
        console.log(err);
        if (err.response?.status === 401) {
            localStorage.removeItem('id');
            dispatch({ type: LOGOUT_USER });
            window.location.href = '/landingPage';
        }
    }
};

优化PrivateOutlet组件

import { useState, useEffect } from 'react';
import { Outlet, Navigate } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux';
import { getCurrentUser } from './actions';

export default function PrivateOutlet() {
    const [isLoaded, setIsLoaded] = useState(false);
    const dispatch = useDispatch();
    // 从Redux获取当前用户状态
    const currentUser = useSelector(state => state.auth.currentUser);

    useEffect(() => {
        dispatch(getCurrentUser())
            .finally(() => setIsLoaded(true)) // 无论成功失败都标记加载完成
    }, [dispatch]);

    if (!isLoaded) return null; // 可替换为加载动画组件

    return currentUser ? <Outlet /> : <Navigate to="/landingPage" replace />;
}

3. 非API事件的权限校验(可选)

如果存在不触发API的操作(如纯本地状态修改),可以封装自定义Hook快速校验权限:

import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';

export const useAuthCheck = () => {
    const currentUser = useSelector(state => state.auth.currentUser);
    const navigate = useNavigate();

    return () => {
        if (!currentUser) {
            navigate('/landingPage', { replace: true });
            return false;
        }
        return true;
    };
};

在组件中使用:

const checkAuth = useAuthCheck();

const handleButtonClick = () => {
    if (!checkAuth()) return;
    // 执行后续操作
};

关键注意事项

  • 所有API请求必须使用封装的Axios实例,确保错误被全局拦截
  • 优先用Redux状态判断登录状态,避免localStorage被篡改或不一致的问题
  • 跳转时使用replace模式,避免用户回退到过期页面

内容的提问来源于stack exchange,提问作者SubrataG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:05:23