温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何使用React Router v6添加身份验证

发布时间:2022-06-01 09:11:40 来源:亿速云 阅读:164 作者:iii 栏目:开发技术

这篇文章主要讲解了“如何使用React Router v6添加身份验证”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用React Router v6添加身份验证”吧!

React Router v6是React应用程序的一个流行且功能强大的路由库。它提供了一种声明式的、基于组件的路由方法,并能处理URL参数、重定向和加载数据等常见任务

这个最新版本的React Router引入了很多新概念,比如<Outlet />layout布局路由,但相关文档仍然很少。

开始

打开终端,运行以下命令创建一个新的 React 项目:

> npx create-react-app ReactRouterAuthDemo > cd ReactRouterAuthDemo

接下来,在 React 应用程序中安装 React Router 作为依赖项:

> npm install react-router-dom

一旦 React Router 依赖项安装好,我们就可以开始编辑src/index.js文件。

首先,从 react-router-dom 中导入 BrowserRouter组件,然后用<BrowserRouter /> 包裹 <App /> 组件,就像这样:

import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import { BrowserRouter } from "react-router-dom"; import App from "./App"; const rootElement = document.getElementById("root"); const root = createRoot(rootElement); root.render(   <StrictMode>     <BrowserRouter>       <App />     </BrowserRouter>   </StrictMode> );

基础路由

React Router提供了 <Routes /><Route /> 组件,使我们能够根据组件的当前位置来渲染它们。

import { Routes, Route } from "react-router-dom"; import { LoginPage } from "./pages/Login"; import { HomePage } from "./pages/Home"; import "./styles.css"; export default function App() {   return (     <Routes>       <Route path="/" element={<HomePage />} />       <Route path="/login" element={<LoginPage />} />     </Routes>   ); }

<Route />提供了应用程序和 React 组件之间路径的映射。例如,当用户导航到/login时,要渲染LoginPage组件,我们只需要像这样提供<Route />:

<Route path="/login" element={<LoginPage />} />

<Route /> 组件可以看作是一个 if 语句,只有当元素与指定的路径匹配时,它才会作用于URL的位置。

<Routes /> 组件是 React Router v5 中的 <Switch /> 组件的替代品。

我们可以通过创建Login.jsxHome.jsx来使用 <Routes />

// Login.jsx export const LoginPage = () => (   <div>     <h2>This is the Login Page</h2>   </div> ); // Home.jsx export const HomePage = () => (   <div>     <h2>This is the Home Page</h2>   </div> );

接下来,我们将运行下面的命令来启动应用程序:

> npm run start

在浏览器中,我们默认会看到Home组件。如果我们使用/login路由,我们将看到LoginPage组件呈现在屏幕上。

或者,我们也可以使用一个普通的JavaScript对象,通过useRoutes钩子来表示应用程序中的路由。这是一种定义路由的功能方法,其工作方式与< routes /><Route />组件相同。

import { useRoutes } from "react-router-dom"; // ... export default function App() {   const routes = useRoutes([     {       path: "/",       element: <HomePage />     },     {       path: "/login",       element: <LoginPage />     }   ]);   return routes; }

既然基本设置已经完成,让我们看看如何创建受保护的路由,从而使未经身份验证的用户无法访问应用程序中的某些内容。

创建受保护的路由

在创建受保护的路由之前,让我们先创建一个自定义钩子,它将使用Context APIuseContext钩子处理通过身份验证的用户的状态。

import { createContext, useContext, useMemo } from "react"; import { useNavigate } from "react-router-dom"; import { useLocalStorage } from "./useLocalStorage"; const AuthContext = createContext(); export const AuthProvider = ({ children }) => {   const [user, setUser] = useLocalStorage("user", null);   const navigate = useNavigate();   // 验证用户权限的时候,访问该函数   const login = async (data) => {     setUser(data);     navigate("/profile");   };   // 登出   const logout = () => {     setUser(null);     navigate("/", { replace: true });   };   const value = useMemo(     () => ({       user,       login,       logout     }),     [user]   );   return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; }; export const useAuth = () => {   return useContext(AuthContext); };

上述 useAuth 钩子中,我们暴露了用户的状态和一些用于用户登录和注销的方法。当用户登出时,我们使用 React RouteruseNavigate 钩子将他们重定向到主页。

为了在页面刷新时保持用户的状态,我们将使用 useLocalStorage 钩子,它将在浏览器的本地存储中同步状态值。

import { useState } from "react"; export const useLocalStorage = (keyName, defaultValue) => {   const [storedValue, setStoredValue] = useState(() => {     try {       const value = window.localStorage.getItem(keyName);       if (value) {         return JSON.parse(value);       } else {         window.localStorage.setItem(keyName, JSON.stringify(defaultValue));         return defaultValue;       }     } catch (err) {       return defaultValue;     }   });   const setValue = (newValue) => {     try {       window.localStorage.setItem(keyName, JSON.stringify(newValue));     } catch (err) {}     setStoredValue(newValue);   };   return [storedValue, setValue]; };

<ProtectedRoute /> 组件将从 useAuth 钩子中检查当前用户的状态,如果用户没有经过身份验证,则重定向到/路径。

import { Navigate } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const ProtectedRoute = ({ children }) => {   const { user } = useAuth();   if (!user) {     // user is not authenticated     return <Navigate to="/" />;   }   return children; };

要重定向用户,我们使用 <Navigate /> 组件。当父组件呈现当前位置时,<Navigate /> 组件会改变当前位置。它在内部使用 usenavate 钩子。

App.js 文件中,我们可以用 <ProtectedRoute /> 组件包装page 组件。例如下面,我们使用 <ProtectedRoute /> 包装<SettingsPage /><ProfilePage /> 组件。现在,当未经身份验证的用户试图访问 /profile/settings 路径时,他们将被重定向到主页。

import { Routes, Route } from "react-router-dom"; import { LoginPage } from "./pages/Login"; import { HomePage } from "./pages/Home"; import { SignUpPage } from "./pages/SignUp"; import { ProfilePage } from "./pages/Profile"; import { SettingsPage } from "./pages/Settings"; import { ProtectedRoute } from "./components/ProtectedRoute"; export default function App() {   return (     <Routes>       <Route path="/" element={<HomePage />} />       <Route path="/login" element={<LoginPage />} />       <Route path="/register" element={<SignUpPage />} />       <Route         path="/profile"         element={           <ProtectedRoute>             <ProfilePage />           </ProtectedRoute>         }       />       <Route         path="/settings"         element={           <ProtectedRoute>             <SettingsPage />           </ProtectedRoute>         }       />     </Routes>   ); }

如果受保护的路由数量有限,上面的方法工作得很好,但如果有多个这样的路由,我们就必须把每个都包装起来,这很繁琐。

相反,我们可以使用React Router v6的嵌套路由特性将所有受保护的路由封装在一个布局中。

使用嵌套路由和< Outlet />

React Router v6中最强大的特性之一是嵌套路由。这个特性允许我们有一个包含其他子路由的路由。我们的大多数布局都与URL上的片段相耦合,React Router完全支持这一点。

例如,我们可以在<HomePage /><LoginPage /> 路由中添加一个父组件 <Route />,就像这样:

import { ProtectedLayout } from "./components/ProtectedLayout"; import { HomeLayout } from "./components/HomeLayout"; // ... export default function App() {   return (     <Routes>       <Route element={<HomeLayout />}>         <Route path="/" element={<HomePage />} />         <Route path="/login" element={<LoginPage />} />       </Route>       <Route path="/dashboard" element={<ProtectedLayout />}>         <Route path="profile" element={<ProfilePage />} />         <Route path="settings" element={<SettingsPage />} />       </Route>     </Routes>   ); }

父组件 <Route /> 也可以有一个路径,它负责在屏幕上呈现子组件<Route />

当用户导航到 /dashboard/profile 时,路由器将呈现 <ProfilePage />。为了实现这一点,父路由元素必须有一个 <Outlet /> 组件来呈现子元素。Outlet 组件使嵌套的 UI 在呈现子路由时可见。

父路由元素还可以具有额外的公共业务逻辑和用户界面。例如,在<ProtectedLayout /> 组件中,我们已经包含了私有路由逻辑和一个通用导航条,当子路由被呈现时,它将是可见的。

import { Navigate, Outlet } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const ProtectedLayout = () => {   const { user } = useAuth();   if (!user) {     return <Navigate to="/" />;   }   return (     <div>       <nav>         <Link to="/settings">Settings</Link>         <Link to="/profile">Profile</Link>       </nav>       <Outlet />     </div>   ) };

除了<Outlet />组件,我们还可以选择使用 useOutlet 钩子,它的作用是一样的:

import { Link, Navigate, useOutlet } from "react-router-dom"; // ... export const ProtectedLayout = () => {   const { user } = useAuth();   const outlet = useOutlet();   if (!user) {     return <Navigate to="/" />;   }   return (     <div>       <nav>         <Link to="/settings">Settings</Link>         <Link to="/profile">Profile</Link>       </nav>       {outlet}     </div>   ); };

与受保护路由类似,我们不希望通过身份验证的用户访问 /login 路径。让我们在 <HomeLayout /> 组件中处理它:

import { Navigate, Outlet } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const HomeLayout = () => {   const { user } = useAuth();   if (user) {     return <Navigate to="/dashboard/profile" />;   }   return (     <div>       <nav>         <Link to="/">Home</Link>         <Link to="/login">Login</Link>       </nav>       <Outlet />     </div>   ) };

感谢各位的阅读,以上就是“如何使用React Router v6添加身份验证”的内容了,经过本文的学习后,相信大家对如何使用React Router v6添加身份验证这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI