使用React路由器V6基本验证路由和重定向
#javascript #初学者 #react #reactrouter

介绍

嗨,

这是关于如何使用React路由器V6使用一些基本身份验证路由的快速教程。这将使您能够保护应用程序中的路线免受未登录的用户的侵害。

您还可以包括针对没有某些团体权限的用户的路线保护(今天不会涵盖,但很容易添加)。

我还将介绍如何将用户导航回他们在登录之前要访问的页面。

让我们开始!

设置我们的项目

首先是制作一个新的香草react项目:

npx create-react-app your-project-name

移动到目录,然后输入:

npm install react-router-dom

组件和路由

继续设置,让我们制作样品组件。

我将创建一个componentsauthcontext文件夹来容纳页面组件,身份验证组件和用户组件:

File Structure

现在,让我们继续进行上下文文件,user.js

如果您不熟悉上下文,则可以从基本上可以阅读有关上下文here.的更多信息,上下文使我们可以为应用程序中的所有组件提供user令牌和setUser函数。这不仅限于usersetUser;您几乎可以将任何想要的道具传递给任何组件。

import React, { useState } from 'react';

const UserContext = React.createContext();

function UserProvider({ children }) {
    const [user, setUser] = useState(false);

    return (
        <UserContext.Provider value={{ user, setUser }}>
            {children}
        </UserContext.Provider>
    )
};

export { UserContext, UserProvider };

我将把user令牌设置为一个简单的状态变量,以便使用按钮将其打开(true)或OFF(false)。如果我们有后端,这是我们将与服务器进行通信以验证用户的地方。

确保记住通过user以及setUser道具,以便其他组件可以访问它们。

接下来,我将在目录的根部打开我的index.js文件,并添加以下行:

`index.js`

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter as Router } from 'react-router-dom';
import { UserProvider } from './context/user';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <UserProvider>
    <Router>
    <App />
    </Router>
  </UserProvider>
);

我将我的<App />组件包装在<UserProvider>中,以使其访问上下文文件和koude18 component(重命名为<Router>)。

对于Admin.jsHomepage.js,让我们既给它们使用<Link />导航的通用模板和一些按钮。

`./components/Admin.js`

import React from 'react'
import { Link } from 'react-router-dom'

function Admin({ setUser }) {
    return (
      <div>
        <h1>Admin</h1>
        <Link to="/" replace><button>Back to Home</button></Link>
      </div>
    )
}

export default Admin

`./components/Homepage.js`

import React from 'react'
import { Link } from 'react-router-dom'

function Homepage({ setUser }) {
  return (
    <div>
      <h1>Homepage</h1>
      <Link to="/admin" replace><button>Admin Page</button></Link>
    </div>
  )
}

export default Homepage

现在,让我们在<App />组件中进行一些路由,也导入我们刚刚制作的组件。

import React, { useContext } from "react";
import { UserContext } from "./context/user";
import Admin from "./components/Admin";
import Homepage from "./components/Homepage";
import { Routes, Route } from "react-router-dom";

function App() {
  const { user, setUser } = useContext(UserContext);

  return (
   <div className="App">
    <Routes>
     <Route path='/' element={<Homepage />} />
     <Route path='/admin' element={<Admin />} />
     <Route path="login" element={<Login />} />
    </Routes>
   </div>
  );
}

export default App;

要测试它,让我们运行npm start

Home

Admin

太好了!现在,我们有了一些基本的路由和一个按钮,使我们可以导航到//admin!现在我们已经建立了所有页面和路线,我们需要保护它们;进入auth.js并设置身份验证!

`./auth/auth.js`

import React from 'react'
import { useLocation, Outlet, Navigate } from 'react-router-dom';

function AuthLayout({ authenticated }) {
    const location = useLocation();
    return authenticated ? <Outlet /> : <Navigate to="/login" 
           replace state={{ from: location }} />;    
};

export default AuthLayout

auth.js中,我们正在导入USEROTICE,OUTLET并从React路由器导航。

这里的返回语句正在寻求检查prop authenticated是真实还是虚假值。 true如果用户已登录,则false如果不是。

<Navigate />如果未登录,将导航用户到/loginuser代币读取false)。我们将用户的当前位置保存到location变量,然后使用<Navigate>中的state={{ from: location }}保存该状态。

(如果您的console.log(location),您可以看到每次URL更改时的状态;在/admin/之间切换时检查控制台!)

最后,<Outlet />将渲染父零件的子组件;在这种情况下,<AuthLayout />将是我们的父组件。 <AuthLayout />下的每个儿童组成部分都会正常呈现时,当user代币读取true

在添加<AuthLayout />之前,我们还需要添加我们的<Login />组件。

./components/Login.js

import React from 'react'
import { useContext } from 'react'
import { UserContext } from '../context/user'

function Login() {
    const { user, setUser } = useContext(UserContext);

    return (
        <div>
            <h1>Login</h1>
            <button onClick={() => setUser(true)}>Login</button>
        </div>
    )
}

export default Login

使用此组件,我们唯一需要的道具是使用上下文的setUser函数。使用此功能,我们可以使用它每次单击登录按钮时登录用户。

Login

现在让我们回到App.js并完成路由。这次,我们将导入<AuthLayout />组件,并将其成为<Homepage /><Admin />的父组件。我们还会导入<Login />,但请保持不受保护。

./App.js

import React, { useContext } from "react";
import { UserContext } from "./context/user";
import Admin from "./components/Admin";
import Homepage from "./components/Homepage";
import Login from "./components/Login";
import AuthLayout from "./auth/auth";
import { Routes, Route } from "react-router-dom";

function App() {
  const { user, setUser } = useContext(UserContext);

return (
<div className="App">
 <Routes>
  <Route element={<AuthLayout authenticated={user} />}>
    <Route path='/' element={<Homepage />} />
    <Route path='/admin' element={<Admin />} />
  </Route>
  <Route path="login" element={<Login />} />
 </Routes>
</div>
  );
}

export default App;

<Route>组件中,我们将<AuthLayout />添加为元素,然后通过user prop。由于现在我们的user代币读取false,它应该自动将我们重定向到/login

由于<Login />不是<AuthLayout />的儿童组成部分,因此即使没有真实的user代币,/login即使可以访问。

继续并再次旋转实例(或保存)以刷新更改。您应该立即注意到您已被重定向到/login。尝试将URL手动更改为//admin,您每次都会被重定向到/login

按下/login上的登录按钮。这是因为我们还没有添加有条件的用户登录后重定向。

让我们回到我们的<Login />组件,然后添加:

./components/Login.js

import React from 'react'
import { useContext } from 'react'
import { UserContext } from '../context/user'
import { useNavigate } from "react-router-dom";

function Login() {
    const { user, setUser } = useContext(UserContext);
    const navigate = useNavigate();

    if(user) {
        navigate('/')
    };

    return (
        <div>
            <h1>Login</h1>
            <button onClick={() => setUser(true)}>Login</button>
        </div>
    );
};

export default Login

如果user令牌是一个真实的值,我们将添加useNavigate以重定向用户。

保存更改,现在尝试登录;登录后,它应该将您重定向到/

登录后重定向用户

现在用户希望能够刷新或直接进入页面,登录,然后保留其位置怎么办?通常,由于我们在<Login />中的有条件,它只是将它们重定向到/

我们可以通过添加有条件使用我们保存在<AuthLayout />中的useLocation状态来解决这个问题!请记住,当游戏机记录location时,它将您的浏览器历史记录保存到location状态。

更新您的<Login />组件:

./components/Login.js 

import React, { useEffect } from 'react'
import { useContext } from 'react'
import { UserContext } from '../context/user'
import { useLocation, useNavigate } from "react-router-dom";

function Login() {
    const { user, setUser } = useContext(UserContext);
    const location = useLocation();
    const navigate = useNavigate();

    if (user && location.state?.from) {
        return navigate(location.state.from)
    };

    return (
        <div>
            <h1>Login</h1>
            <button onClick={() => setUser(true)}>Login</button>
        </div>
    )
}

export default Login

我们添加了一个不同的条件,该条件检查user令牌是否为真,location具有可用的状态,我们可以用来与navigate重定向。

要测试此问题,让我们更新我们的<Homepage /><Admin />组件以包括注销按钮。我们还将更新<App />以通过setUser Prop,但如果您愿意,也可以使用上下文。

./App.js

import React, { useContext } from "react";
import { UserContext } from "./context/user";
import Admin from "./components/Admin";
import Homepage from "./components/Homepage";
import Login from "./components/Login";
import AuthLayout from "./auth/auth";
import { Routes, Route } from "react-router-dom";

function App() {
  const { user, setUser } = useContext(UserContext);

return (
<div className="App">
 <Routes>
  <Route element={<AuthLayout authenticated={user} />}>
    <Route path='/' element={<Homepage {setUser}=setUser />} />
    <Route path='/admin' element={<Admin {setUser}=setUser  />} />
  </Route>
  <Route path="login" element={<Login />} />
 </Routes>
</div>
  );
}

export default App;

./components/Homepage.js

import React from 'react'
import { Link } from 'react-router-dom'

function Homepage({ setUser }) {
  return (
    <div>
      <h1>Homepage</h1>
      <Link to="/admin" replace><button>Admin Page</button></Link>
      <button onClick={() => setUser(false)}>Logout</button>
    </div>
  )
}

export default Homepage

./components/Admin.js

import React from 'react'
import { Link } from 'react-router-dom'

function Admin({ setUser }) {
    return (
      <div>
         <h1>Admin</h1>
         <Link to="/" replace><button>Back to Home</button></Link>
         <button onClick={() => setUser(false)}>Logout</button>
      </div>
    )
}

export default Admin

保存更改或再次旋转实例,然后继续登录。

登录后,使用按钮将其导航到/admin,然后注销。登录后,当您再次登录时,您应该注意到您已返回到/admin页面,而不是/

结论

React Router Router V6是一种非常强大的工具,可用于登录后的身份验证和有条件重定向。

笔记

如果我犯了任何错误或您有任何疑问,请在评论中告诉我!对ReactJ和React Router V6仍然是新手,但我希望这很有用!

学分

React Router v6 Documentation

Creating Protected Routes

Redirect After Login with React Router v6 (video)