[英]Private Routing is not getting set in React App
在我的 React 应用程序中,当用户成功签名后,他/她的信息将保存在本地存储中。 只有当用户成功登录时,令牌才会保存在 session 存储中。
现在我知道只有当用户成功登录时,令牌才会在 session 存储中。基于此令牌,我想设置我的私有路由。
我尝试过类似的事情,如果令牌是 null 那么它应该保留在登录表单上,如果令牌不是 null 然后 go 到主页但这样做不是设置我的路由。
我想也许我在运行路由器、路由和路由的 App.js 文件中犯了一些错误,或者我正在检查令牌是 null 还是不是 null 我在那里犯了一些错误。
请帮助我纠正我的错误。 谢谢。
这是我的代码。
登录.js
import React, { useState } from "react";
import { Form, Button } from "react-bootstrap";
import { Link } from "react-router-dom";
const Login = ({ setTokenData }) => {
const initialValues = {
email: "",
password: "",
};
const [userData, setUserData] = useState(initialValues);
const authenticateUser = () => {
const localInfo = JSON.parse(localStorage.getItem("signUpUser"));
localInfo?.map((item) => {
const userName = item.email;
const userPassword = item.password;
if (userName === userData.email && userPassword === userData.password) {
console.log("success");
const token = Math.random().toString(36).substr(2, 5);
console.log("token is:", token);
sessionStorage.setItem("token", JSON.stringify(token));
setTokenData(token);
} else {
console.log("failure");
return false;
}
});
setUserData(initialValues);
};
return (
<>
<Form className="loginForm">
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email Address</Form.Label>
<Form.Control
type="email"
placeholder="Enter email"
value={userData.email}
name="email"
onChange={(e) =>
setUserData({ ...userData, [e.target.name]: e.target.value })
}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
placeholder="Password"
name="password"
value={userData.password}
onChange={(e) =>
setUserData({ ...userData, [e.target.name]: e.target.value })
}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicCheckbox"></Form.Group>
<Button
variant="primary"
type="submit"
onClick={() => authenticateUser()}
>
Login
</Button>
<div className="txtToSignUpBtn">
<span>OR</span> <Link to="/signUp">Click here to Register</Link>
</div>
</Form>
</>
);
};
export default Login;
PrivateRoute.js
import React from 'react'
import { Navigate } from 'react-router-dom';
import Login from "./Login";
import Header from "./Header";
const getTokenData = () => {
const token = JSON.parse(sessionStorage.getItem("token"));
if (token) {
return JSON.parse(sessionStorage.getItem("token"));
} else {
return null;
}
};
const RequireAuth = () => {
const [tokenData, setTokenData] = useState(getTokenData());
if (tokenData === null) {
return <Login setTokenData={setTokenData} />,
<Navigate to='/' />
} else {
return <Header setTokenData={setTokenData} />,
<Navigate to='/home' />
}
export default RequireAuth;
应用程序.js
import { Layout } from "antd";
import React from "react";
import SignUp from "./SignUp";
import Login from "./Login";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Header from "./Header";
import UsersTable from "./UsersTable";
import RequireAuth from "./PrivateRoute";
const AppWrapper = () => {
return (
<>
<Layout>
<Router>
<Routes>
<Route
exact
path="/home"
element={
<RequireAuth>
<Header />
</RequireAuth>
}
/>
<Route exact path="/signUp" element={<SignUp />} />
<Route exact path="/" element={<Login />} />
<Route exact path="/usersTable" element={<UsersTable />} />
</Routes>
</Router>
</Layout>
</>
);
};
export default AppWrapper;
您应该为 Route 创建单独的组件,例如 PrivateRoute 并将您的组件包装在 PrivateRoute
我想为您提供一个代码示例,但我在以下网站上找到了一个很好的示例https://blog.netcetera.com/how-to-create-guarded-routes-for-your-react-app-d2fe7c7b6122
我认为您对RequireAuth
身份验证包装器的想法是正确的。 我建议更紧密地与 RRDv6 路由包装器范例保持一致。 让您的RequireAuth
简单地检查 session 存储,如果经过身份验证,则呈现一个Outlet
,如果没有,则重定向到登录路由。
示例:这会获取用户尝试访问的当前位置,并将其在路由 state 中传递到登录路由,以便用户可以被重定向回他们最初尝试访问的路由。 经过身份验证后, Outlet
会呈现嵌套的Route
组件。
const RequireAuth = () => {
const location = useLocation();
const tokenData = getTokenData();
return tokenData ? (
<Outlet />
) : (
<Navigate to="/login" state={{ from: location }} replace />
);
};
用法:这里的"/usersTable"
被放置在嵌套在渲染RequreAuth
包装器的路由中的路由上。 如果用户未经身份验证并尝试访问此路由,他们将被退回到"/login"
路由进行登录,并且在身份验证成功后将被重定向回"/usersTable"
。
<Routes>
<Route path="/" element={<h1>Home</h1>} />
<Route path="/signUp" element={<SignUp />} />
<Route path="/login" element={<Login />} />
<Route element={<RequireAuth />}>
<Route path="/usersTable" element={<UsersTable />} />
</Route>
</Routes>
完整的沙盒代码:
import {
BrowserRouter as Router,
Routes,
Route,
Link,
Navigate,
Outlet,
useLocation,
useNavigate
} from "react-router-dom";
const getTokenData = () => {
return JSON.parse(sessionStorage.getItem("token"));
};
const RequireAuth = () => {
const location = useLocation();
const tokenData = getTokenData();
return tokenData ? (
<Outlet />
) : (
<Navigate to="/login" state={{ from: location }} replace />
);
};
const Header = () => (
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/login">Login</Link>
</li>
<li>
<Link to="/signUp">Sign Up</Link>
</li>
<li>
<Link to="/usersTable">Users Table</Link>
</li>
</ul>
);
const SignUp = () => <h1>SignUp</h1>;
const UsersTable = () => <h1>UsersTable</h1>;
const Login = () => {
const navigate = useNavigate();
const { state } = useLocation();
const { from = "/" } = state || {};
const authenticate = () => {
sessionStorage.setItem("token", JSON.stringify(true));
navigate(from, { replace: true });
};
const deauthenticate = () => {
sessionStorage.removeItem("token");
navigate("/", { replace: true });
};
return (
<>
<h1>Login</h1>
{getTokenData() ? (
<button type="button" onClick={deauthenticate}>
Log out
</button>
) : (
<button type="button" onClick={authenticate}>
Log in
</button>
)}
</>
);
};
export default function App() {
return (
<Router>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
<Header />
<Routes>
<Route path="/" element={<h1>Home</h1>} />
<Route path="/signUp" element={<SignUp />} />
<Route path="/login" element={<Login />} />
<Route element={<RequireAuth />}>
<Route path="/usersTable" element={<UsersTable />} />
</Route>
</Routes>
</Router>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.