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.