React Router 6刷新页面后如何保留在受保护路由?
解决React Router 6刷新受保护路由跳转首页的问题
问题根源
刷新页面后Redux状态重置,loadUser异步请求完成前,isAuthenticated处于未认证状态,同时路由结构不符合React Router 6规范,导致页面错误跳转。
解决方案
1. 修复路由结构(必须用<Routes>包裹)
React Router 6要求所有<Route>必须放在<Routes>组件内部,否则路由匹配会异常。修改App.js:
import { Routes, Route } from 'react-router-dom'; // 导入Login等组件 export default function App() { useEffect(() => { store.dispatch(loadUser()) }, []) return ( <Routes> <Route path="/" element={<Home />} /> <Route element={<Protected />}> <Route path="profile" element={<Profile />} /> </Route> <Route path="/login" element={<Login />} /> </Routes> ) }
2. 优化Protected路由,避免加载时跳转
在loadUser请求过程中,加入加载状态判断,不要直接跳转,等请求完成后再做认证判断:
import { useSelector } from 'react-redux' import { Navigate, Outlet } from 'react-router-dom' const Protected = () => { const { isAuthenticated, loading } = useSelector(state => state.auth) // 加载中时显示加载组件,避免过早跳转 if (loading) { return <div>加载中...</div>; // 替换成你的自定义加载组件 } return isAuthenticated ? <Outlet /> : <Navigate to='/login' replace />; } export default Protected
3. 修正authReducer初始状态
确保初始状态包含loading和isAuthenticated字段,避免undefined导致的逻辑错误:
export const authReducer = (state = { user: {}, isAuthenticated: false, loading: false }, action) => { switch (action.type) { case LOGIN_REQ: case REGISTER_REQ: case LOAD_USER_REQ: return { ...state, // 保留原有状态,避免覆盖user等字段 isAuthenticated: false, loading: true } // ... 其他case保持不变 default: return state } }
4. 确保请求携带认证Token
刷新页面时,axios请求需要自动携带登录时存储的Token,否则/api/profile会返回401。在全局配置axios拦截器:
// 在userActions.js或单独的axios配置文件中 import axios from 'axios'; axios.interceptors.request.use( config => { // 假设登录成功后将Token存在localStorage const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, error => Promise.reject(error) );
完成以上步骤后,刷新profile页面时,会先显示加载状态,等loadUser请求成功并更新Redux状态后,自动渲染Profile组件,不会跳转到首页。
内容的提问来源于stack exchange,提问作者5fingered sloth
相关产品推荐
相关产品推荐

