错误: [ PrivateRoute ]不是 < Route > 组件。 < Routes > 的所有组件子级必须是 < Route > 或 < React. Fragment >

我正在使用 React 路由器 v6,并且正在为我的应用程序创建私有路由。

Private Route.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

路线 J文件中,我写道:

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

我已经通过相同的例子 Ref = “ noReferrer”> React-router Auth Example-StackBlitz,file App.tsx 反应路由器的授权示例-StackBlitz,文件 App.tsx

有什么我不知道的吗?

150097 次浏览

今天我遇到了同样的问题,并且在 安德鲁 · 卢卡很有帮助的文章的基础上提出了下面的解决方案

在 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>

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

只有 Route组件可以是 Routes的子组件。如果您遵循 v6文档,那么您将看到身份验证模式是使用包装器组件来处理身份验证检查和重定向。

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>
}
/>

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

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>
}
/>

我知道这并不是如何使 PirvateRoute工作的诀窍,但是我只是想提一下,新的文档推荐了一种稍微不同的方法来处理 反应路由器 v6的这种模式:

<Route path="/protected" element={<RequireAuth><ProtectedPage /></RequireAuth>} />
import { Navigate, useLocation } from "react-router";


export const RequireAuth: React.FC<{ children: JSX.Element }> = ({ children }) => {
let auth = useAuth();
let location = useLocation();


if (!auth.user) {
return <Navigate to="/login" state=\{\{ from: location }} />;
}


return children;
};

如果你需要的话,你应该在 ProtectedPage内部添加更多的路由。

请参阅 文件一个例子了解更多细节。另外,请检查迈克尔杰克逊的 这张纸条,其中包含了一些实现细节。

反应路由器 v6,一些语法糖:

{auth && (
privateRoutes.map(route =>
<Route
path={route.path}
key={route.path}
element={auth.isAuthenticated ? <route.component /> : <Navigate to={ROUTE_WELCOME_PAGE} replace />}
/>
)
)}

只要将你的路由器组件设置为元素道具:

<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>

你也可以检查 从 V5升级

更长的元素

        <Router>
<div>
<Navbar totalItems={cart.total_items}/>
<Routes>
<Route exact path='/'>
<Route exact path='/' element={<Products products={products} onAddToCart={handleAddToCart}/>}/>
</Route>
<Route exact path='/cart'>
<Route exact path='/cart' element={<Cart cart={cart}/>}/>
</Route>
</Routes>
</div>
</Router>
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";


function App() {
return (
<Router>
<Routes>
<Route path="/" element={<h1>home page</h1>} />
<Route path="/seacrch" element={<h1>seacrch page</h1>} />
</Routes>
</Router>
);
}


export default App;

页眉将停留在所有页面上

import React from 'react';


import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";


const Header = () => <h2>Header</h2>
const Dashboard = () => <h2>Dashboard</h2>
const SurveyNew = () => <h2>SurveyNew</h2>
const Landing = () => <h2>Landing</h2>




const App = () =>{
return (
<div>
<BrowserRouter>
<Header />
<Routes >
<Route exact path="/" element={<Landing />} />
<Route path="/surveys" element={<Dashboard />}  />
<Route path="/surveys/new" element={<SurveyNew/>}  />
</Routes>
</BrowserRouter>
</div>
);
};
export default App;

补充减少代码行,使其更具可读性和美观。

这可能只是一个评论,但我没有足够的点,所以我会 把它作为一个答案。

达林的回答 有效,但 德鲁的回答更好!为了完成 Drew 关于美学的回答,我建议创建一个私有组件,将组件作为道具而不是儿童。

私有路由文件/组件的基本示例:

import { Navigate } from 'react-router-dom';


const Private = (Component) => {
const auth = false; //your logic


return auth ? <Component /> : <Navigate to="/login" />
}

路由文件示例:

<Routes>
<Route path="/home" element={<Home />} />
<Route path="/user" element={<Private Component={User} />} />
</Routes>

对于错误”[ Navigate ]不是 < Route > 组件。< 路由 > 的所有子组件必须是 < 路由 > 或 < 反应。片段 >”,使用以下方法或许可以解决:

当没有匹配的路由器时,跳转到 DefaultPage

<Navigate to={window.location.pathname + '/kanban'}/>

参见 一个 href = “ https://reacrouter.com/docs/en/v6/getting-start/lessons # Index-Routes”rel = “ nofollow noReferrer”> Index Routes

<Routes>


<Route path={'/default'} element={<DefaultPage/>}/>


<Route path={'/second'}  element={<SecondPage/>}/>


{/* <Navigate to={window.location.pathname + '/kanban'}/> */}
<Route index element={<DefaultPage/>} />


</Routes>

您可以将函数用于私有路由:

<Route exact path="/login" element={NotAuth(Login)} />
<Route exact path="/Register" element={NotAuth(Register)} />


function NotAuth(Component) {
if (isAuth)
return <Navigate to="/" />;
return <Component />;
}

从项目中删除 PrivateRoute 组件,并在 App.js 文件中使用以下代码:

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


...


<Route exact path="/home" element={<Home/>}/>
<Route exact path="/" element={isauth ? <Dashboard/> : <Navigate to="/Home"  />}/>

我试了所有的答案,但总是显示出错误:

错误: [ PrivateRoute ]不是一个组件。所有组件的子级必须是 a 或 < React. Fragment >

但我找到了一个解决方案))-

在 PrivateRoute.js 文件中:

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


const PrivateRoute = ({ children }) => {
const authed = isauth()


return authed ? children : <Navigate to={"/Home" /> };


export default ProtectedRoute;

路线 J文件中:

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

这是创建私人路线的简单方法:

import React from 'react'
import { Navigate } from 'react-router-dom'
import { useAuth } from '../../context/AuthContext'


export default function PrivateRoute({ children }) {
const { currentUser } = useAuth()


if (!currentUser) {
return <Navigate to='/login' />
}


return children;
}

现在,如果我们想为 Dashboard 组件添加一个私有路由,我们可以应用这个私有路由,如下所示:

<Routes>
<Route exact path="/" element={<PrivateRoute><Dashboard /></PrivateRoute>} />
</Routes>
<Route path='/' element={<Navigate to="/search" />} />

我使用的是“ response-router-dom”: “ ^ 6.3.0”,我就是这样做的

私有路由组件和路由

   import {Route} from "react-router-dom";


const PrivateRoute = ({ component: Compontent, authenticated }) => {
return authenticated ? <Compontent /> : <Navigate to="/" />;
}
    

<Route
path="/user/profile"
element={<PrivateRoute authenticated={true} component={Profile} />} />

路线的子元素需要是 路线元素,所以我们可以改变 受保护路线:

export type ProtectedRouteProps = {
isAuth: boolean;
authPath: string;
outlet: JSX.Element;
};


export default function ProtectedRoute({
isAuth,
authPath,
outlet,
}: ProtectedRouteProps) {
if (isAuth) {
return outlet;
} else {
return <Navigate to=\{\{pathname: authPath}} />;
}
}

然后像这样使用它:

const defaultProps: Omit<ProtectedRouteProps, 'outlet'> = {
isAuth: //check if user is authenticated,
authPath: '/login',
};


return (
<div>
<Routes>
<Route path="/" element={<ProtectedRoute {...defaultProps} outlet={<HomePage />} />} />
</Routes>
</div>
);

现在是2022年,我做了如下的事情:

// routes.tsx


import { lazy } from "react";
import { Routes, Route } from "react-router-dom";
import Private from "./Private";
import Public from "./Public";


const Home = lazy(() => import("../pages/Home/Home"));
const Signin = lazy(() => import("../pages/Signin/Signin"));


export const Router = () => {
return (
<Routes>
<Route path="/" element={Private(<Home />)} />
<Route path="/signin" element={Public(<Signin />)} />
</Routes>
);
};
// Private.tsx


import { Navigate } from "react-router-dom";
import { useEffect, useState } from "react";


function render(c: JSX.Element) {
return c;
}


const Private = (Component: JSX.Element) => {
const [hasSession, setHasSession] = useState<boolean>(false);


useEffect(() => {
(async function () {
const sessionStatus = await checkLoginSession();


setHasSession(Boolean(sessionStatus));
})();
}, [hasSession, Component]);




return hasSession ? render(Component) : <Navigate to="signin" />;
};


export default Private;


希望这个能帮上忙!