React,使用 React Router Dom 通过身份验证实现受保护的路由
React, implementing protected route with authentication with React Router Dom
即使在成功登录后也无法路由到 admin
页面,显示空白屏幕。成功登录后,系统应导航并显示管理屏幕。有人可以告诉为什么路由没有发生吗?
//login.js
import React, { useEffect, useState } from 'react';
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
const Login = () =>{
const { register, errors, handleSubmit } = useForm();
const [loginData, setLoginData] = useState("");
const [helperText, setHelperText] = useState('');
const navigate = useNavigate();
const onSubmit = (data) => {
try {
const userEmail = "dev@test.com"; // for time being just hard code data
const userPassword = "somePass123"; // for time being just hard code data
if(data.email === userEmail && data.password === userPassword ){
localStorage.setItem('loginEmail', userEmail);
setLoginData(userEmail);
navigate('/admin');
window.location.reload(true)
} else {
setHelperText("Invalid login details");
}
} catch (e){
console.log(e);
}
};
console.log(errors);
return (
<div className="wrapper">
<h3>Login</h3>
<section className="col2">
<div className='loginSection'>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Email</label>
<input
type="text"
{...register("email", { required: true})}
/>
<label>Password</label>
<input
type="text"
{...register("password", { required: true})}
/>
<label>
<span className="loginValidationText">{helperText}</span>
</label>
<section className="col4">
<input type="submit" />
</section>
</form>
</div>
</section>
</div>
)
}
export default Login
//protectedRoute.js
import React from "react";
import { Route, BrowserRouter } from "react-router-dom";
export const ProtectedRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={(props) => {
if (localStorage.getItem("loginEmail")) {
return <Component {...props} />;
} else {
return (
<>
<BrowserRouter
to={{
pathname: "/login",
state: {
from: props.location,
},
}}
/>
</>
);
}
}}
/>
);
};
//navigation.js
import React from 'react';
import { NavLink} from 'react-router-dom';
const Navigation = () => {
return (
<div className="App">
<div className="wrapper">
<div id="wrap">
<nav className="siteNavigation_nav_links">
<div className="main_links_nav">
<img className='logoimage' alt="SSS Logo" src="/images/super.png"></img>
<div className="navigationpanel">
<NavLink className="mob_link" to="/">Home</NavLink>
<NavLink className="mob_link" to="/team">Team</NavLink>
<NavLink className="mob_link" to="/login">Login</NavLink>
</div>
</div>
</nav>
</div>
</div>
</div>
)
}
导出默认导航;
//App.js
import React, { useEffect, useState } from 'react';
import { BrowserRouter, Route, Routes, Switch} from "react-router-dom";
import Navigation from './components/navigation';
import Home from "./components/home";
import Team from "./components/team";
import Admin from "./components/admin";
import Login from "./components/login";
import { ProtectedRoute } from "./components/protectedRoute";
function App() {
return (
<BrowserRouter>
<Navigation />
<Routes>
<Route path="/" element={<Home />}>
</Route>
<Route path="/team" element={<Team />}>
</Route>
<Route path="/login" element={<Login />}>
</Route>
<Route path="/admin" element={
<ProtectedRoute >
<Admin />
</ProtectedRoute>
}>
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;
将 PotectedRoute.js
更改为下面的代码,因为您所做的更像我们以前为 React Router Dom v5.
所做的
import React from "react";
import { Navigate, useLocation} from "react-router-dom";
export const ProtectedRoute = ({children}) => {
let location = useLocation();
if(!localStorage.getItem("loginEmail")){
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
};
来自 useLocation
的信息作为 prop 传递给 Navigate
可以在 Login
中使用,因此您可以将用户发送到特定的 url 他们要去的地方一个硬编码的(在你的情况下是管理员),如果你有多个受保护的路由,这很有用。虽然这不是必需的,但您可以将其删除。
To know more about authentication in React Router Dom v6, visit this example on StackBlitz from their documentation.
即使在成功登录后也无法路由到 admin
页面,显示空白屏幕。成功登录后,系统应导航并显示管理屏幕。有人可以告诉为什么路由没有发生吗?
//login.js
import React, { useEffect, useState } from 'react';
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
const Login = () =>{
const { register, errors, handleSubmit } = useForm();
const [loginData, setLoginData] = useState("");
const [helperText, setHelperText] = useState('');
const navigate = useNavigate();
const onSubmit = (data) => {
try {
const userEmail = "dev@test.com"; // for time being just hard code data
const userPassword = "somePass123"; // for time being just hard code data
if(data.email === userEmail && data.password === userPassword ){
localStorage.setItem('loginEmail', userEmail);
setLoginData(userEmail);
navigate('/admin');
window.location.reload(true)
} else {
setHelperText("Invalid login details");
}
} catch (e){
console.log(e);
}
};
console.log(errors);
return (
<div className="wrapper">
<h3>Login</h3>
<section className="col2">
<div className='loginSection'>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Email</label>
<input
type="text"
{...register("email", { required: true})}
/>
<label>Password</label>
<input
type="text"
{...register("password", { required: true})}
/>
<label>
<span className="loginValidationText">{helperText}</span>
</label>
<section className="col4">
<input type="submit" />
</section>
</form>
</div>
</section>
</div>
)
}
export default Login
//protectedRoute.js
import React from "react";
import { Route, BrowserRouter } from "react-router-dom";
export const ProtectedRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={(props) => {
if (localStorage.getItem("loginEmail")) {
return <Component {...props} />;
} else {
return (
<>
<BrowserRouter
to={{
pathname: "/login",
state: {
from: props.location,
},
}}
/>
</>
);
}
}}
/>
);
};
//navigation.js
import React from 'react';
import { NavLink} from 'react-router-dom';
const Navigation = () => {
return (
<div className="App">
<div className="wrapper">
<div id="wrap">
<nav className="siteNavigation_nav_links">
<div className="main_links_nav">
<img className='logoimage' alt="SSS Logo" src="/images/super.png"></img>
<div className="navigationpanel">
<NavLink className="mob_link" to="/">Home</NavLink>
<NavLink className="mob_link" to="/team">Team</NavLink>
<NavLink className="mob_link" to="/login">Login</NavLink>
</div>
</div>
</nav>
</div>
</div>
</div>
)
}
导出默认导航;
//App.js
import React, { useEffect, useState } from 'react';
import { BrowserRouter, Route, Routes, Switch} from "react-router-dom";
import Navigation from './components/navigation';
import Home from "./components/home";
import Team from "./components/team";
import Admin from "./components/admin";
import Login from "./components/login";
import { ProtectedRoute } from "./components/protectedRoute";
function App() {
return (
<BrowserRouter>
<Navigation />
<Routes>
<Route path="/" element={<Home />}>
</Route>
<Route path="/team" element={<Team />}>
</Route>
<Route path="/login" element={<Login />}>
</Route>
<Route path="/admin" element={
<ProtectedRoute >
<Admin />
</ProtectedRoute>
}>
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;
将 PotectedRoute.js
更改为下面的代码,因为您所做的更像我们以前为 React Router Dom v5.
import React from "react";
import { Navigate, useLocation} from "react-router-dom";
export const ProtectedRoute = ({children}) => {
let location = useLocation();
if(!localStorage.getItem("loginEmail")){
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
};
来自 useLocation
的信息作为 prop 传递给 Navigate
可以在 Login
中使用,因此您可以将用户发送到特定的 url 他们要去的地方一个硬编码的(在你的情况下是管理员),如果你有多个受保护的路由,这很有用。虽然这不是必需的,但您可以将其删除。
To know more about authentication in React Router Dom v6, visit this example on StackBlitz from their documentation.