【发布时间】:2021-05-26 18:35:51
【问题描述】:
我正在尝试实现仅在用户登录后才能访问的受保护路由。
基本上有两条路线:/loginLogin 组件(公共)和/Dashboard 组件(受保护)。用户点击/login中的Login按钮后,会调用一个API,返回一个accessToken,然后存储在localStorage中。 protectedRoute HOC 检查令牌是否存在于 localStorage 中并相应地重定向用户。
点击Login 按钮后,它只是重定向回登录页面,而不是把用户带到Dashboard。不知道逻辑有什么问题。
asyncLocalStorage 只是基于 Promise 的 localStorage 操作的辅助方法。
App.js
import { useEffect, useState } from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Dashboard from "./Dashboard";
import Login from "./Login";
import ProtectedRoute from "./ProtectedRoute";
import { asyncLocalStorage } from "./asyncLocalStorage";
function App() {
const [auth, setAuth] = useState(false);
useEffect(() => {
const getToken = async () => {
const token = await asyncLocalStorage.getItem("accessToken");
if (token) setAuth(true);
};
getToken();
}, []);
return (
<div className="app">
<Router>
<Switch>
<ProtectedRoute exact path="/" isLoggedIn={auth} redirectTo="/login">
<Dashboard />
</ProtectedRoute>
<Route exact path="/login">
<Login />
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
ProtectedRoute.js
import { Route, Redirect } from "react-router-dom";
const ProtectedRoute = ({ children, isLoggedIn, redirectTo, ...rest }) => {
return (
<Route
{...rest}
render={() => {
return isLoggedIn ? children : <Redirect to={redirectTo} />;
}}
/>
);
};
export default ProtectedRoute;
仪表板.js
const Dashboard = () => {
return (
<div>
<h3>Dashboard</h3>
<button
onClick={() => {
localStorage.removeItem("accessToken");
window.location.href = "/login";
}}
>
Logout
</button>
</div>
);
};
export default Dashboard;
登录.js
import { asyncLocalStorage } from "./asyncLocalStorage";
const Login = () => {
return (
<div>
<h3>Login</h3>
<button
onClick={async () => {
// Making an API call here and storing the accessToken in localStorage.
await asyncLocalStorage.setItem(
"accessToken",
"SOME_TOKEN_FROM_API_RES"
);
window.location.href = "/";
}}
>
Login
</button>
</div>
);
};
export default Login;
asyncLocalStorage.js
export const asyncLocalStorage = {
setItem: (key, value) => {
Promise.resolve(localStorage.setItem(key, value));
},
getItem: (key) => {
return Promise.resolve(localStorage.getItem(key));
}
};
【问题讨论】:
-
异步操作的顺序经常是个问题。我看到您正在使用
await,但您可能仍然在设置auth之前点击重定向。这有帮助吗?:stackoverflow.com/a/66358676/10431574 -
找到了!就是你只在挂载时运行设置
auth一次的效果,所以ProtectedRoute总是 得到isLoggedIn={false}。
标签: javascript reactjs authentication react-router react-router-dom