reactjs - React Router onEnter 与 Redux 身份验证
问题描述
我正在尝试使用路由器的 onEnterreact-router-dom
来验证用户是否经过身份验证。我将身份验证保留在登录减速器中。
初始状态:
const initialState = {
logged: false,
userName: null
}
在我的 App.js 我有我的路由器
import React from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import { useSelector } from "react-redux";
import Home from './Home';
import Login from './Login';
function App() {
const login = useSelector((state) => state.login);
const requireAuth = (nextState, replace, next) => {
console.log(login)
if(!login.logged) {
replace({
pathname: "/login",
state: {nextPathname: nextState.location.pathname}
});
}
next();
}
return (
<Router>
<Switch>
<Route exact path="/" component={Home} onEnter={requireAuth} />
<Route exact path="/login" component={Login} />
</Switch>
</Router>
)
}
export default App;
它不会重定向到/login
. 实际上,它没有调用requireAuth
函数,因为浏览器没有显示函数内部的日志。我在路由器设置中缺少什么?顺便说一句,在导航到页面之前检查用户是否经过身份验证是否合适?
谢谢
使用更新的代码PrivateRoute
。错误:Error: Maximum update depth exceeded.
import React from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Redirect
} from "react-router-dom";
import { useSelector } from "react-redux";
import Home from './Home';
import Login from './Login';
function App() {
const PrivateRoute = ({ children, ...rest }) => {
const login = useSelector((state) => state.login);
console.log(login);
return (
<Route
{...rest}
render={({ location }) =>
login.logged ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}
return (
<Router>
<Switch>
<PrivateRoute path="/">
<Home />
</PrivateRoute>
<Route path="/login">
<Login />
</Route>
</Switch>
</Router>
)
}
export default App;
解决方案
不,最好的方法是您可以在react-router 示例页面中看到的内容。
您最好像这样定义到您的私人页面的路线:
function PrivateRoute({ children, ...rest }) {
const login = useSelector((state) => state.login);
return (
<Route
{...rest}
render={({ location }) =>
login ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location }
}}
/>
)
}
/>
);
}
然后像这样使用它:
<Switch>
<Route path="/public">
<PublicPage />
</Route>
<Route path="/login">
<LoginPage />
</Route>
<PrivateRoute path="/protected">
<ProtectedPage />
</PrivateRoute>
</Switch>
更新:
你更新了你的帖子,对于那些可能犯这个错误的人:
在更新的代码中,我们有这个开关结构:
<Switch>
<PrivateRoute path="/">
<Home />
</PrivateRoute>
<Route path="/login">
<Login />
</Route>
</Switch>
当我们将用户重定向到/login
页面时。它也与第一条路线 ( /
) 匹配。所以Switch
选择第一个PrivateRoute
渲染,它会形成一个无限循环。
有两种方法可以解决这个问题:
首先:在Switch
层次结构中将更长和更具体的路线放在首位。例如在您的代码中,您可以这样做:
<Switch>
<Route path="/login">
<Login />
</Route>
<PrivateRoute path="/">
<Home />
</PrivateRoute>
</Switch>
第二:exact
在更通用的路线中首先使用:
<Switch>
<PrivateRoute exact path="/">
<Home />
</PrivateRoute>
<Route path="/login">
<Login />
</Route>
</Switch>
推荐阅读
- abaqus - 在 Abaqus 中的 *Instance entry 中计算平移和旋转轴和角度
- javascript - 使用 vuex mapGetters 在用户的状态 obj 中进行迭代
- python - 在我的 Python 脚本中从 Delphi DLL 获取 PChar 参数
- c++ - 如何使用 ndk-build.cmd 构建 Android .so 文件
- node.js - 为什么等待后的布尔赋值会触发原子更新错误?
- excel - Excel宏循环范围
- sapui5 - SAP Cloud 应用程序编程模型集成
- android - 如何使 Android RecyclerView 响应最初适合屏幕?
- python - Apache Airflow - 在 dag 和日期更改的每个任务中重新运行 Prescript
- java - 无法识别 ADB 命令