使用React Router v6 進行身份驗證完全指南

      網友投稿 1267 2022-05-30

      React Router v6是React應用程序的一個流行且功能強大的路由庫。它提供了一種聲明式的、基于組件的路由方法,并能處理URL參數、重定向和加載數據等常見任務。

      這個最新版本的React Router引入了很多新概念,比如和layout布局路由,但相關文檔仍然很少。

      本文將演示如何使用React Router v6創建受保護的路由以及如何添加身份驗證。

      開始

      打開終端,運行以下命令創建一個新的 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組件,然后用 包裹 組件,就像這樣:

      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( );

      基礎路由

      React Router提供了 組件,使我們能夠根據組件的當前位置來渲染它們。

      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 ( } /> } /> ); }

      提供了應用程序和 React 組件之間路徑的映射。例如,當用戶導航到/login時,要渲染LoginPage組件,我們只需要像這樣提供:

      } />

      組件可以看作是一個 if 語句,只有當元素與指定的路徑匹配時,它才會作用于URL的位置。

      組件是 React Router v5 中的 組件的替代品。

      我們可以通過創建Login.jsx和Home.jsx來使用

      // Login.jsx export const LoginPage = () => (

      This is the Login Page

      ); // Home.jsx export const HomePage = () => (

      This is the Home Page

      );

      接下來,我們將運行下面的命令來啟動應用程序:

      > npm run start

      在瀏覽器中,我們默認會看到Home組件。如果我們使用/login路由,我們將看到LoginPage組件呈現在屏幕上。

      或者,我們也可以使用一個普通的JavaScript對象,通過useRoutes鉤子來表示應用程序中的路由。這是一種定義路由的功能方法,其工作方式與< routes />和組件相同。

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

      既然基本設置已經完成,讓我們看看如何創建受保護的路由,從而使未經身份驗證的用戶無法訪問應用程序中的某些內容。

      創建受保護的路由

      在創建受保護的路由之前,讓我們先創建一個自定義鉤子,它將使用Context API和useContext鉤子處理通過身份驗證的用戶的狀態。

      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 {children}; }; export const useAuth = () => { return useContext(AuthContext); };

      上述 useAuth 鉤子中,我們暴露了用戶的狀態和一些用于用戶登錄和注銷的方法。當用戶登出時,我們使用 React Router 的 useNavigate 鉤子將他們重定向到主頁。

      為了在頁面刷新時保持用戶的狀態,我們將使用 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]; };

      組件將從 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 ; } return children; };

      要重定向用戶,我們使用 組件。當父組件呈現當前位置時, 組件會改變當前位置。它在內部使用 usenavate 鉤子。

      在 App.js 文件中,我們可以用 組件包裝page 組件。例如下面,我們使用 包裝 組件。現在,當未經身份驗證的用戶試圖訪問 /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 ( } /> } /> } /> } /> } /> ); }

      如果受保護的路由數量有限,上面的方法工作得很好,但如果有多個這樣的路由,我們就必須把每個都包裝起來,這很繁瑣。

      相反,我們可以使用React Router v6的嵌套路由特性,將所有受保護的路由封裝在一個布局中。

      使用嵌套路由和< Outlet />

      React Router v6中最強大的特性之一是嵌套路由。這個特性允許我們有一個包含其他子路由的路由。我們的大多數布局都與URL上的片段相耦合,React Router完全支持這一點。

      例如,我們可以在 路由中添加一個父組件 ,就像這樣:

      import { ProtectedLayout } from "./components/ProtectedLayout"; import { HomeLayout } from "./components/HomeLayout"; // ... export default function App() { return ( }> } /> } /> }> } /> } /> ); }

      使用React Router v6 進行身份驗證完全指南

      父組件 也可以有一個路徑,它負責在屏幕上呈現子組件

      當用戶導航到 /dashboard/profile 時,路由器將呈現 。為了實現這一點,父路由元素必須有一個 組件來呈現子元素。Outlet 組件使嵌套的 UI 在呈現子路由時可見。

      父路由元素還可以具有額外的公共業務邏輯和用戶界面。例如,在 組件中,我們已經包含了私有路由邏輯和一個通用導航條,當子路由被呈現時,它將是可見的。

      import { Navigate, Outlet } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const ProtectedLayout = () => { const { user } = useAuth(); if (!user) { return ; } return (

      ) };

      除了組件,我們還可以選擇使用 useOutlet 鉤子,它的作用是一樣的:

      import { Link, Navigate, useOutlet } from "react-router-dom"; // ... export const ProtectedLayout = () => { const { user } = useAuth(); const outlet = useOutlet(); if (!user) { return ; } return (

      {outlet}
      ); };

      與受保護路由類似,我們不希望通過身份驗證的用戶訪問 /login 路徑。讓我們在 組件中處理它:

      import { Navigate, Outlet } from "react-router-dom"; import { useAuth } from "../hooks/useAuth"; export const HomeLayout = () => { const { user } = useAuth(); if (user) { return ; } return (

      ) };

      結尾

      值得花一些時間來更好地理解 React Router v6 的工作原理,特別是用戶身份驗證。

      與以前的版本相比,React Router v6是一個巨大的改進。它快速、穩定、可靠。除了更容易使用之外,它還有很多新特性,比如和一個改進的組件,這大大簡化了 React 應用中的路由。

      我希望本指南對您有所幫助,希望您對如何使用React Router v6處理用戶身份驗證有了更好的理解。

      React

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:【分布式框架】深入理解分布式之緩存擊穿
      下一篇:分布式事務解決方案:Spring Cloud + Nacos + Seata整合
      相關文章
      亚洲另类自拍丝袜第1页| 中文字幕精品亚洲无线码二区| 亚洲色成人网站WWW永久| 亚洲 自拍 另类小说综合图区| 亚洲av无码av在线播放| 亚洲一本一道一区二区三区| 亚洲欧洲国产综合AV无码久久| 精品亚洲AV无码一区二区三区| 亚洲六月丁香六月婷婷色伊人| 亚洲嫩草影院在线观看| 亚洲国产av一区二区三区丶| 亚洲免费在线观看视频| 亚洲黄页网在线观看| 亚洲人成电影网站色| 亚洲av无码偷拍在线观看| 色欲色欲天天天www亚洲伊| 精品亚洲国产成人av| 亚洲成人一区二区| 亚洲Av无码国产情品久久| 国产专区一va亚洲v天堂| 亚洲一区二区三区偷拍女厕| 亚洲成AV人片在线观看无码 | 久久亚洲日韩看片无码| 99久久亚洲精品无码毛片| 亚洲成年人电影在线观看| 亚洲人成人网毛片在线播放| 亚洲欧洲国产综合AV无码久久| 在线91精品亚洲网站精品成人| 亚洲黄片手机免费观看| 亚洲级αV无码毛片久久精品| 亚洲福利视频一区| 亚洲成人免费在线观看| 亚洲精品无码久久久久牙蜜区| 亚洲AⅤ视频一区二区三区 | 欧洲 亚洲 国产图片综合| 亚洲av无码日韩av无码网站冲| 国产成人高清亚洲| 久久精品国产亚洲香蕉| 亚洲日本国产精华液| 亚洲国产AV一区二区三区四区| 亚洲国产精品一区二区第四页|