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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 02:03:12