React Router v6中实现PrivateRoute用户鉴权遇阻求助
React Router v6 结合 Redux 实现 PrivateRoute 正确方案
1. 先明确 React Router v6 的核心变化
v6 不再支持自定义 <Route> 组件,而是要写一个权限校验包裹组件,用来包裹需要保护的页面元素,而非替换原生 Route。
2. 修正 PrivateRoute 组件代码
恢复 Redux 连接,明确接收 children 属性,根据认证状态决定渲染内容:
// /src/common/PrivateRoute.js import React from 'react'; import { Navigate } from "react-router-dom"; import { connect } from "react-redux"; import PropTypes from "prop-types"; // 接收需要保护的子组件和Redux中的auth状态 const PrivateRoute = ({ auth, children }) => { // 处理初始化加载状态(isAuthenticated初始为null) if (auth.isLoading) { return <div>加载中...</div>; } // 已认证则渲染子组件,未认证跳转到登录页 return auth.isAuthenticated ? children : <Navigate to='/login' />; }; // 定义props类型校验 PrivateRoute.propTypes = { auth: PropTypes.object.isRequired }; // 从Redux store映射auth状态到组件props const mapStateToProps = state => ({ auth: state.auth }); // 连接Redux并导出组件 export default connect(mapStateToProps)(PrivateRoute);
3. 修正 App.js 中的路由用法
注意:你之前把登录页放在 PrivateRoute 里是错误的——登录/注册页应该是公开访问的,需要保护的是 Dashboard 这类核心页面:
// App.js import PrivateRoute from './common/PrivateRoute'; <Routes> {/* 保护Dashboard路由,仅认证用户可访问 */} <Route path="/" element={ <PrivateRoute> <Dashboard /> </PrivateRoute> } /> {/* 公开路由,无需权限校验 */} <Route path="/login" element={<Login />} /> <Route path="/register" element={<Register />} /> </Routes>
4. 完善 Redux Auth Reducer 逻辑
你的 auth reducer 目前只有默认返回,需要补充登录/登出的状态更新逻辑,这样 PrivateRoute 才能正确判断认证状态:
// /src/reducers/auth.js const initialState = { token: localStorage.getItem('token'), isAuthenticated: null, isLoading: false, user: null }; export default function(state = initialState, action) { switch (action.type) { case 'USER_LOADING': return { ...state, isLoading: true }; case 'USER_LOADED': return { ...state, isAuthenticated: true, isLoading: false, user: action.payload }; case 'LOGIN_SUCCESS': localStorage.setItem('token', action.payload.token); return { ...state, ...action.payload, isAuthenticated: true, isLoading: false }; case 'AUTH_ERROR': case 'LOGOUT_SUCCESS': localStorage.removeItem('token'); return { ...state, token: null, user: null, isAuthenticated: false, isLoading: false }; default: return state; } }
问题说明
- 之前用
children报错是因为组件没有接收该属性,现在明确声明并渲染即可解决。 - 初始状态
isAuthenticated: null是为了区分“未初始化”和“未认证”,避免页面出现不必要的跳转闪烁。
内容的提问来源于stack exchange,提问作者Sid
相关产品推荐
相关产品推荐

