介绍
嗨,
这是关于如何使用React路由器V6使用一些基本身份验证路由的快速教程。这将使您能够保护应用程序中的路线免受未登录的用户的侵害。
您还可以包括针对没有某些团体权限的用户的路线保护(今天不会涵盖,但很容易添加)。
我还将介绍如何将用户导航回他们在登录之前要访问的页面。
让我们开始!
设置我们的项目
首先是制作一个新的香草react项目:
npx create-react-app your-project-name
移动到目录,然后输入:
npm install react-router-dom
组件和路由
继续设置,让我们制作样品组件。
我将创建一个components
,auth
和context
文件夹来容纳页面组件,身份验证组件和用户组件:
现在,让我们继续进行上下文文件,user.js
。
如果您不熟悉上下文,则可以从基本上可以阅读有关上下文here.的更多信息,上下文使我们可以为应用程序中的所有组件提供user
令牌和setUser
函数。这不仅限于user
和setUser
;您几乎可以将任何想要的道具传递给任何组件。
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.js
和Homepage.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
。
太好了!现在,我们有了一些基本的路由和一个按钮,使我们可以导航到/
和/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 />
如果未登录,将导航用户到/login
(user
代币读取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
函数。使用此功能,我们可以使用它每次单击登录按钮时登录用户。
现在让我们回到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仍然是新手,但我希望这很有用!