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

react-router-dom 6.8.0自定义PrivateRoute报错,如何正确使用?

自定义PrivateRoute的正确实现与使用

我正在为聊天应用构建自定义PrivateRoute,以下是我的PrivateRoute代码及使用方式,但构建项目时出现错误,请问该如何正确使用自定义PrivateRoute?

原代码示例

import { useState, useEffect } from 'react';
import { Route, Navigate } from 'react-router-dom';
import axios from 'axios';

interface PrivateRouteProps {
  element: React.ComponentType<any>;
  path: string;
}

export function PrivateRoute({ element: Element, path }: PrivateRouteProps) {
  const [authenticated, setAuthenticated] = useState(false);

  useEffect(() => {
    axios
      .get('http://golang:8080')
      .then((response) => {
        if (response.status === 200) {
          setAuthenticated(true);
        }
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  return (
    <Route
      path={path}
      element={
        authenticated ? <Element /> : <Navigate to="/login" replace={true} />
      }
    />
  );
}

原使用方式

<PrivateRoute path={RouterPath.ROOT} element={Main} />

问题分析

  1. React Router v6 API适配问题:v6版本不再支持自定义Route组件,Routes仅识别官方Route组件,自定义PrivateRoute作为Route的用法会被忽略。
  2. 初始状态逻辑缺陷:authenticated初始值为false,鉴权请求未完成时就会强制跳转到登录页,导致用户体验差。
  3. 类型定义错误:element属性定义为ComponentType<any>,但实际使用时传入的是组件实例(如<Main />),类型不匹配。

修正后的PrivateRoute实现

import { useState, useEffect } from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import axios from 'axios';

interface PrivateRouteProps {
  children: React.ReactElement;
}

export function PrivateRoute({ children }: PrivateRouteProps) {
  // 初始为null表示鉴权请求未完成
  const [authenticated, setAuthenticated] = useState<boolean | null>(null);
  const location = useLocation();

  useEffect(() => {
    const checkAuthentication = async () => {
      try {
        const response = await axios.get('http://golang:8080');
        setAuthenticated(response.status === 200);
      } catch (error) {
        console.error('鉴权失败:', error);
        setAuthenticated(false);
      }
    };

    checkAuthentication();
  }, []);

  // 鉴权中显示加载状态
  if (authenticated === null) {
    return <div>加载中...</div>; // 替换为你的自定义加载UI
  }

  // 鉴权通过则渲染子组件,否则跳转到登录页并保存当前路径
  return authenticated ? (
    children
  ) : (
    <Navigate to="/login" replace state={{ from: location }} />
  );
}

正确使用方式

在路由配置中,用PrivateRoute包裹需要保护的组件:

import { Routes, Route } from 'react-router-dom';
import { PrivateRoute } from './PrivateRoute';
import Main from './Main';
import Login from './Login';

function AppRoutes() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route path={RouterPath.ROOT} element={
        <PrivateRoute>
          <Main />
        </PrivateRoute>
      } />
    </Routes>
  );
}

关键改进点

  • 采用组件包裹的方式适配React Router v6的API,符合官方推荐的路由保护方案。
  • 增加加载状态,避免鉴权请求未完成时的错误跳转。
  • 使用useLocation保存当前路径,登录完成后可跳回原页面(在Login组件中可通过useLocation().state?.from获取)。
  • 修正类型定义,使用children接收组件实例,匹配实际使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:32:54