使用React?Router?v6?添加身份驗(yàn)證的方法
React Router v6是React應(yīng)用程序的一個(gè)流行且功能強(qiáng)大的路由庫。它提供了一種聲明式的、基于組件的路由方法,并能處理URL參數(shù)、重定向和加載數(shù)據(jù)等常見任務(wù)。
這個(gè)最新版本的React Router引入了很多新概念,比如<Outlet />和layout布局路由,但相關(guān)文檔仍然很少。
本文將演示如何使用React Router v6創(chuàng)建受保護(hù)的路由以及如何添加身份驗(yàn)證。
開始
打開終端,運(yùn)行以下命令創(chuàng)建一個(gè)新的 React 項(xiàng)目:
> npx create-react-app ReactRouterAuthDemo > cd ReactRouterAuthDemo
接下來,在 React 應(yīng)用程序中安裝 React Router 作為依賴項(xiàng):
> npm install react-router-dom
一旦 React Router 依賴項(xiàng)安裝好,我們就可以開始編輯src/index.js文件。
首先,從 react-router-dom 中導(dǎo)入 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>
);基礎(chǔ)路由
React Router提供了 <Routes /> 和 <Route /> 組件,使我們能夠根據(jù)組件的當(dāng)前位置來渲染它們。
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 />提供了應(yīng)用程序和 React 組件之間路徑的映射。例如,當(dāng)用戶導(dǎo)航到/login時(shí),要渲染LoginPage組件,我們只需要像這樣提供<Route />:
<Route path="/login" element={<LoginPage />} /><Route /> 組件可以看作是一個(gè) if 語句,只有當(dāng)元素與指定的路徑匹配時(shí),它才會作用于URL的位置。
<Routes /> 組件是 React Router v5 中的 <Switch /> 組件的替代品。
我們可以通過創(chuàng)建Login.jsx和Home.jsx來使用 <Routes />:
// Login.jsx
export const LoginPage = () => (
<div>
<h1>This is the Login Page</h1>
</div>
);
// Home.jsx
export const HomePage = () => (
<div>
<h1>This is the Home Page</h1>
</div>
);接下來,我們將運(yùn)行下面的命令來啟動應(yīng)用程序:
> npm run start
在瀏覽器中,我們默認(rèn)會看到Home組件。如果我們使用/login路由,我們將看到LoginPage組件呈現(xiàn)在屏幕上。
或者,我們也可以使用一個(gè)普通的JavaScript對象,通過useRoutes鉤子來表示應(yīng)用程序中的路由。這是一種定義路由的功能方法,其工作方式與< routes />和<Route />組件相同。
import { useRoutes } from "react-router-dom";
// ...
export default function App() {
const routes = useRoutes([
{
path: "/",
element: <HomePage />
},
{
path: "/login",
element: <LoginPage />
}
]);
return routes;
}既然基本設(shè)置已經(jīng)完成,讓我們看看如何創(chuàng)建受保護(hù)的路由,從而使未經(jīng)身份驗(yàn)證的用戶無法訪問應(yīng)用程序中的某些內(nèi)容。
創(chuàng)建受保護(hù)的路由
在創(chuàng)建受保護(hù)的路由之前,讓我們先創(chuàng)建一個(gè)自定義鉤子,它將使用Context API和useContext鉤子處理通過身份驗(yàn)證的用戶的狀態(tài)。
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();
// 驗(yàn)證用戶權(quán)限的時(shí)候,訪問該函數(shù)
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 鉤子中,我們暴露了用戶的狀態(tài)和一些用于用戶登錄和注銷的方法。當(dāng)用戶登出時(shí),我們使用 React Router 的 useNavigate 鉤子將他們重定向到主頁。
為了在頁面刷新時(shí)保持用戶的狀態(tài),我們將使用 useLocalStorage 鉤子,它將在瀏覽器的本地存儲中同步狀態(tài)值。
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 鉤子中檢查當(dāng)前用戶的狀態(tài),如果用戶沒有經(jīng)過身份驗(yàn)證,則重定向到/路徑。
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 /> 組件。當(dāng)父組件呈現(xiàn)當(dāng)前位置時(shí),<Navigate /> 組件會改變當(dāng)前位置。它在內(nèi)部使用 usenavate 鉤子。
在 App.js 文件中,我們可以用 <ProtectedRoute /> 組件包裝page 組件。例如下面,我們使用 <ProtectedRoute /> 包裝<SettingsPage /> 和 <ProfilePage /> 組件?,F(xiàn)在,當(dāng)未經(jīng)身份驗(yàn)證的用戶試圖訪問 /profile 或 /settings 路徑時(shí),他們將被重定向到主頁。
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>
);
}如果受保護(hù)的路由數(shù)量有限,上面的方法工作得很好,但如果有多個(gè)這樣的路由,我們就必須把每個(gè)都包裝起來,這很繁瑣。
相反,我們可以使用React Router v6的嵌套路由特性,將所有受保護(hù)的路由封裝在一個(gè)布局中。
使用嵌套路由和< Outlet />
React Router v6中最強(qiáng)大的特性之一是嵌套路由。這個(gè)特性允許我們有一個(gè)包含其他子路由的路由。我們的大多數(shù)布局都與URL上的片段相耦合,React Router完全支持這一點(diǎn)。
例如,我們可以在<HomePage /> 和 <LoginPage /> 路由中添加一個(gè)父組件 <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 /> 也可以有一個(gè)路徑,它負(fù)責(zé)在屏幕上呈現(xiàn)子組件<Route />。
當(dāng)用戶導(dǎo)航到 /dashboard/profile 時(shí),路由器將呈現(xiàn) <ProfilePage />。為了實(shí)現(xiàn)這一點(diǎn),父路由元素必須有一個(gè) <Outlet /> 組件來呈現(xiàn)子元素。Outlet 組件使嵌套的 UI 在呈現(xiàn)子路由時(shí)可見。
父路由元素還可以具有額外的公共業(yè)務(wù)邏輯和用戶界面。例如,在<ProtectedLayout /> 組件中,我們已經(jīng)包含了私有路由邏輯和一個(gè)通用導(dǎo)航條,當(dāng)子路由被呈現(xiàn)時(shí),它將是可見的。
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>
);
};與受保護(hù)路由類似,我們不希望通過身份驗(yàn)證的用戶訪問 /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>
)
};結(jié)尾
值得花一些時(shí)間來更好地理解 React Router v6 的工作原理,特別是用戶身份驗(yàn)證。
與以前的版本相比,React Router v6是一個(gè)巨大的改進(jìn)。它快速、穩(wěn)定、可靠。除了更容易使用之外,它還有很多新特性,比如<Outlets />和一個(gè)改進(jìn)的<Route />組件,這大大簡化了 React 應(yīng)用中的路由。
我希望本指南對您有所幫助,希望您對如何使用React Router v6處理用戶身份驗(yàn)證有了更好的理解。
到此這篇關(guān)于使用React Router v6 進(jìn)行身份驗(yàn)證完全指南的文章就介紹到這了,更多相關(guān)React Router v6驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React?Fiber?樹思想解決業(yè)務(wù)實(shí)際場景詳解
這篇文章主要為大家介紹了React?Fiber?樹思想解決業(yè)務(wù)實(shí)際場景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
React中Portals與錯(cuò)誤邊界處理實(shí)現(xiàn)
本文主要介紹了React中Portals與錯(cuò)誤邊界處理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
React?Native實(shí)現(xiàn)Toast輕提示和loading效果
這篇文章主要介紹了React Native實(shí)現(xiàn)Toast輕提示和loading效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
next-redux-wrapper使用細(xì)節(jié)及源碼分析
這篇文章主要為大家介紹了next-redux-wrapper使用細(xì)節(jié)及源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Reactjs實(shí)現(xiàn)通用分頁組件的實(shí)例代碼
這篇文章主要介紹了Reactjs實(shí)現(xiàn)通用分頁組件的實(shí)例代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-01-01
如何解決React官方腳手架不支持Less的問題(小結(jié))
這篇文章主要介紹了如何解決React官方腳手架不支持Less的問題(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
react-router-domV6版本的路由和嵌套路由寫法詳解
本文主要介紹了react-router-domV6版本的路由和嵌套路由寫法詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

