错误:[专用路由] 不是<路由>组件。<路由>的所有组件子级都必须是<路由>或<React.Fragment>

2022-08-30 04:20:04

我正在使用 React Router v6,并为我的应用程序创建专用路由。

在文件PrivateRoute.js,我有代码

import React from 'react';
import {Route,Navigate} from "react-router-dom";
import {isauth}  from 'auth'

function PrivateRoute({ element, path }) {
  const authed = isauth() // isauth() returns true or false based on localStorage
  const ele = authed === true ? element : <Navigate to="/Home"  />;
  return <Route path={path} element={ele} />;
}

export default PrivateRoute

在文件路由中.js我写如下:

 ...
<PrivateRoute exact path="/" element={<Dashboard/>}/>
<Route exact path="/home" element={<Home/>}/>

我已经经历了相同的示例 React-router 身份验证示例 - StackBlitz,文件 App.tsx

我错过了什么吗?


答案 1

我今天遇到了同样的问题,并根据Andrew Luca的这篇非常有用的文章提出了以下解决方案。

在 PrivateRoute 中.js:

import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';

const PrivateRoute = () => {
    const auth = null; // determine if authorized, from context or however you're doing it

    // If authorized, return an outlet that will render child elements
    // If not, return element that will navigate to login page
    return auth ? <Outlet /> : <Navigate to="/login" />;
}

在App.js(我留下了其他一些页面作为示例):

import './App.css';
import React, {Fragment} from 'react';
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import Navbar from './components/layout/Navbar';
import Home from './components/pages/Home';
import Register from './components/auth/Register'
import Login from './components/auth/Login';
import PrivateRoute from './components/routing/PrivateRoute';

const App = () => {
  return (
    <Router>
      <Fragment>
        <Navbar/>
        <Routes>
          <Route exact path='/' element={<PrivateRoute/>}>
            <Route exact path='/' element={<Home/>}/>
          </Route>
          <Route exact path='/register' element={<Register/>}/>
          <Route exact path='/login' element={<Login/>}/>
        </Routes>
      </Fragment>
    </Router>
    
  );
}

在上面的路由中,这是专用路由:

<Route exact path='/' element={<PrivateRoute/>}>
      <Route exact path='/' element={<Home/>}/>
</Route>

如果授权成功,将显示该元素。否则,它将导航到登录页面。


答案 2

只有组件可以是 的子级。如果您按照 v6 文档进行操作,则会看到身份验证模式是使用包装器组件来处理身份验证检查和重定向。RouteRoutes

function RequireAuth({ children }: { children: JSX.Element }) {
  let auth = useAuth();
  let location = useLocation();

  if (!auth.user) {
    // Redirect them to the /login page, but save the current location they were
    // trying to go to when they were redirected. This allows us to send them
    // along to that page after they login, which is a nicer user experience
    // than dropping them off on the home page.
    return <Navigate to="/login" state={{ from: location }} />;
  }

  return children;
}

...

<Route
  path="/protected"
  element={
    <RequireAuth>
      <ProtectedPage />
    </RequireAuth>
  }
/>

创建自定义组件的旧 v5 模式不再有效。使用代码/逻辑更新的 v6 模式可能如下所示:Route

const PrivateRoute = ({ children }) => {
  const authed = isauth() // isauth() returns true or false based on localStorage
  
  return authed ? children : <Navigate to="/Home" />;
}

并使用

<Route
  path="/dashboard"
  element={
    <PrivateRoute>
      <Dashboard />
    </PrivateRoute>
  }
/>