React V6 路由保护和组件内路由
React V6 route guarding and routing within component
我正在尝试为我的项目使用 React Routing V6。
目前我正在努力使身份验证和路由本身正常工作。
我的代码的想法是:
未通过身份验证的用户:
使用我的登录组件重定向到 /login。 (仅登录组件)
已验证用户:
加载 gameComponent
组件,gamecomponent
中的其余链接将加载到名为 middleContentHolder
[=22 的 gameComponents div class 中=]
例子:
已验证用户:
访问 url /crime -> 加载游戏组件,并在游戏组件内加载 crime
组件。
访问 url /test -> 加载 gamecomponent ,并在 gamecomponent 中加载 SideBarRight
组件。
未通过身份验证的用户:
vitits url /crime -> 未验证 -> 重定向到 /login
-> 仅加载登录模块。
请注意,在 gamecomponent 组件中,我确实有将在 gamecomponent 中加载的链接。
app.js 将加载游戏组件,如果未授权则重定向用户登录。
app.js:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import GameComponent from './gameComponent.jsx';
import { BrowserRouter as Router } from 'react-router-dom';
import { Routes, Route, Navigate, Outlet } from 'react-router-dom';
import Crime from './components/game/crime.jsx';
import PrivateRoute from './PrivateRoute';
import Login from './components/login/login.jsx';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<GameComponent />}>
<PrivateRoute isAuth={true} path="crime" component={Crime} redirectTo='/login'/>
</Route>
</Routes>
</Router>
);
}
export default App;
游戏组件:
import React, {Component} from 'react';
//import Component from 'react-dom';
import SideBarRight from './components/game/sideBarRight.jsx';
import SideBarLeft from './components/game/sideBarLeft.jsx';
import Crime from './components/game/crime.jsx';
import Login from './components/login/login.jsx';
import './gameComponent.css';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { BrowserRouter} from "react-router-dom";
class GameComponent extends Component{
constructor() {
super();
this.state = {
userData: {
user: {cash:0, bank:0, weapon:'', username: 'test', locationname: 'Bankok',
defence: 0},
rankbar: {rankpercent: 50, rank: 'Mafia'},
}
}
}
render() {
return (
<div className="main">
<div className="sidebar left">
<SideBarLeft/>
</div>
<div className="middleContentHolder">
<Route path="/" element={<Crime />} />
<Route path="/test" element={<Crime />} />
<Route path="/crime" element={<Crime />} />
<Route path="/test" element={<SideBarRight UserData={this.state.userData} />} />
<div className="col-8">
<div className="content">
<div className="header"><span>Test...</span></div>
</div>
</div>
</div>
<div className="sidebar right">
<SideBarRight UserData={this.state.userData}/>
</div>
</div>
);
}
}
export default GameComponent;
PrivateRoute
:(auth 只是一个虚拟的 atm)
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Navigate } from 'react-router-dom';
import { useNavigate } from "react-router-dom";
import Login from './components/login/login.jsx';
import GameComponent from './gameComponent.jsx';
const PrivateRoute = ({ component: Component, redirectTo, isAuth, path, ...props }) => {
isAuth = false;
if(!isAuth) {
return <Navigate to={redirectTo} />;
}
return <Route path={path} element={<Component />} />
};
export default PrivateRoute;
更新:
原始授权was:in 私有路由:
isAuth = isAuth;
一个显示我想要的非工作代码示例:
<PrivateRoute isAuth={true} path="/" component={GameComponent} redirectTo='/login'>
rest of routes exist in gamecomponent..
</PrivateRoute>
如果您只想 GameComponent
在使用经过身份验证时加载,则需要像这样更改 App
组件:
function App() {
return (
<Router>
<Routes>
<Route path="/login" element={<LoginComponent />} />
<PrivateRoute isAuth={true} path="/" component={GameComponent} redirectTo='/login'/>
</Routes>
</Router>
);
}
这里我们实际上是在放置一个开关,以便我们可以在没有身份验证的情况下导航到 /login
。 <Routes>
在这里很重要,因为它只会渲染与 path
.
完全匹配的组件
随着React Router V6的正式发布,其他答案不再有效。它会抛出错误,因为 <PrivateRoute />
不是 <Route />
.
正确的方法是像这样重构您的 <PrivateRoute />
组件...
import { Navigate, useLocation } from "react-router-dom"
const PrivateRoute = (props: { children: React.ReactNode }): JSX.Element => {
const { children } = props
// Up to you specific app to decide how to get this value
const isLoggedIn: boolean = localStorage.getItem('logged_user') !== null;
const location = useLocation()
return isLoggedIn ? (
<>{children}</>
) : (
<Navigate
replace={true}
to="/login"
state={{ from: `${location.pathname}${location.search}` }}
/>
)
}
那么无论你在哪个文件中设置你的路线,你都会做...
<Routes>
<Route path="/PRIVATE" element={<PrivateRoute> <PrivatePage /> </PrivateRoute>}/>
<Route path="/profile" element={<PrivateRoute> <ProfilePage /> </PrivateRoute>}/>
<Route path="/login" element={<LoginPage />}/>
<Route path="/" element={<HomePage />}/>
</Routes>
这是在 V6 中正确的做法,因为只有 <Route />
可以嵌套在 <Routes />
中。然后你的认证逻辑被移动到 element
prop.
作为额外的奖励,PrivateRoute 中的 state={{ from: `${location.pathname}${location.search}` }}
允许您获得他们试图进入但被拒绝的页面的 URL。这将传递到您的登录页面,您可以在他们进行身份验证后将他们重定向回 URL。
我正在尝试为我的项目使用 React Routing V6。
目前我正在努力使身份验证和路由本身正常工作。 我的代码的想法是:
未通过身份验证的用户:
使用我的登录组件重定向到 /login。 (仅登录组件)
已验证用户:
加载 gameComponent
组件,gamecomponent
中的其余链接将加载到名为 middleContentHolder
[=22 的 gameComponents div class 中=]
例子:
已验证用户:
访问 url /crime -> 加载游戏组件,并在游戏组件内加载 crime
组件。
访问 url /test -> 加载 gamecomponent ,并在 gamecomponent 中加载 SideBarRight
组件。
未通过身份验证的用户:
vitits url /crime -> 未验证 -> 重定向到 /login
-> 仅加载登录模块。
请注意,在 gamecomponent 组件中,我确实有将在 gamecomponent 中加载的链接。 app.js 将加载游戏组件,如果未授权则重定向用户登录。
app.js:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import GameComponent from './gameComponent.jsx';
import { BrowserRouter as Router } from 'react-router-dom';
import { Routes, Route, Navigate, Outlet } from 'react-router-dom';
import Crime from './components/game/crime.jsx';
import PrivateRoute from './PrivateRoute';
import Login from './components/login/login.jsx';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<GameComponent />}>
<PrivateRoute isAuth={true} path="crime" component={Crime} redirectTo='/login'/>
</Route>
</Routes>
</Router>
);
}
export default App;
游戏组件:
import React, {Component} from 'react';
//import Component from 'react-dom';
import SideBarRight from './components/game/sideBarRight.jsx';
import SideBarLeft from './components/game/sideBarLeft.jsx';
import Crime from './components/game/crime.jsx';
import Login from './components/login/login.jsx';
import './gameComponent.css';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import { BrowserRouter} from "react-router-dom";
class GameComponent extends Component{
constructor() {
super();
this.state = {
userData: {
user: {cash:0, bank:0, weapon:'', username: 'test', locationname: 'Bankok',
defence: 0},
rankbar: {rankpercent: 50, rank: 'Mafia'},
}
}
}
render() {
return (
<div className="main">
<div className="sidebar left">
<SideBarLeft/>
</div>
<div className="middleContentHolder">
<Route path="/" element={<Crime />} />
<Route path="/test" element={<Crime />} />
<Route path="/crime" element={<Crime />} />
<Route path="/test" element={<SideBarRight UserData={this.state.userData} />} />
<div className="col-8">
<div className="content">
<div className="header"><span>Test...</span></div>
</div>
</div>
</div>
<div className="sidebar right">
<SideBarRight UserData={this.state.userData}/>
</div>
</div>
);
}
}
export default GameComponent;
PrivateRoute
:(auth 只是一个虚拟的 atm)
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Navigate } from 'react-router-dom';
import { useNavigate } from "react-router-dom";
import Login from './components/login/login.jsx';
import GameComponent from './gameComponent.jsx';
const PrivateRoute = ({ component: Component, redirectTo, isAuth, path, ...props }) => {
isAuth = false;
if(!isAuth) {
return <Navigate to={redirectTo} />;
}
return <Route path={path} element={<Component />} />
};
export default PrivateRoute;
更新:
原始授权was:in 私有路由:
isAuth = isAuth;
一个显示我想要的非工作代码示例:
<PrivateRoute isAuth={true} path="/" component={GameComponent} redirectTo='/login'>
rest of routes exist in gamecomponent..
</PrivateRoute>
如果您只想 GameComponent
在使用经过身份验证时加载,则需要像这样更改 App
组件:
function App() {
return (
<Router>
<Routes>
<Route path="/login" element={<LoginComponent />} />
<PrivateRoute isAuth={true} path="/" component={GameComponent} redirectTo='/login'/>
</Routes>
</Router>
);
}
这里我们实际上是在放置一个开关,以便我们可以在没有身份验证的情况下导航到 /login
。 <Routes>
在这里很重要,因为它只会渲染与 path
.
随着React Router V6的正式发布,其他答案不再有效。它会抛出错误,因为 <PrivateRoute />
不是 <Route />
.
正确的方法是像这样重构您的 <PrivateRoute />
组件...
import { Navigate, useLocation } from "react-router-dom"
const PrivateRoute = (props: { children: React.ReactNode }): JSX.Element => {
const { children } = props
// Up to you specific app to decide how to get this value
const isLoggedIn: boolean = localStorage.getItem('logged_user') !== null;
const location = useLocation()
return isLoggedIn ? (
<>{children}</>
) : (
<Navigate
replace={true}
to="/login"
state={{ from: `${location.pathname}${location.search}` }}
/>
)
}
那么无论你在哪个文件中设置你的路线,你都会做...
<Routes>
<Route path="/PRIVATE" element={<PrivateRoute> <PrivatePage /> </PrivateRoute>}/>
<Route path="/profile" element={<PrivateRoute> <ProfilePage /> </PrivateRoute>}/>
<Route path="/login" element={<LoginPage />}/>
<Route path="/" element={<HomePage />}/>
</Routes>
这是在 V6 中正确的做法,因为只有 <Route />
可以嵌套在 <Routes />
中。然后你的认证逻辑被移动到 element
prop.
作为额外的奖励,PrivateRoute 中的 state={{ from: `${location.pathname}${location.search}` }}
允许您获得他们试图进入但被拒绝的页面的 URL。这将传递到您的登录页面,您可以在他们进行身份验证后将他们重定向回 URL。