<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
此範例演示了一個包含三個頁面的簡單登入流程:公共頁面、受保護頁面和登入頁面。 為了檢視受保護的頁面,你必須先登入。
首先,存取公共頁面。 然後,存取受保護的頁面。 你尚未登入,因此你將被重定向到登入頁面。 登入後,你將被重定向回受保護的頁面。
首先封裝AuthProvider
元件,利用Context
特性共用那些對於一個元件樹而言是“全域性”的資料。
全域性定義user
、signIn
、signOut
資料和方法,signIn
、signOut
使用了高階函數,也方便後續擴充套件和修改。
Context
主要應用場景在於很多不同層級的元件需要存取同樣一些的資料。請謹慎使用,因為這會使得元件的複用性變差。
如果你只是想避免層層傳遞一些屬性,元件組合(component composition)有時候是一個比Context
更好的解決方案。
import { ReactNode, createContext, useState } from "react"; export interface AuthContextType { user: any; signIn: (user: string, callback: VoidFunction) => void; signOut: (callback: VoidFunction) => void; } export let AuthContext = createContext<AuthContextType | null>(null); const fakeAuthProvider = { isAuthenticated: false, signIn(callback: VoidFunction) { this.isAuthenticated = true; setTimeout(callback, 100); }, signOut(callback: VoidFunction) { this.isAuthenticated = false; setTimeout(callback, 100); }, }; const AuthProvider = ({ children }: { children: ReactNode }) => { const [user, setUser] = useState<any>(null); let signIn = (newUser: string, callback: VoidFunction) => { return fakeAuthProvider.signIn(() => { setUser(newUser); callback(); }); }; let signOut = (callback: VoidFunction) => { return fakeAuthProvider.signOut(() => { setUser(null); callback(); }); }; return ( <AuthContext.Provider value={{ user, signIn, signOut }}> {children} </AuthContext.Provider> ); }; export default AuthProvider;
Layout
元件主要是針對登入狀態進行校驗,然後做相應處理。利用react-router
v6中<Outlet />
元件顯示巢狀路由,相比於v5版本v6實現巢狀路由更加方便,省略了很多冗餘的判斷程式碼。
import { useContext } from "react"; import { useNavigate, Link, Outlet } from "react-router-dom"; import { AuthContext, AuthContextType } from "../AuthProvider"; const useAuth = () => useContext(AuthContext); const AuthStatus = () => { let auth = useAuth(); let { user, signOut } = auth as AuthContextType; let navigate = useNavigate(); if (!user) return <p>沒有登入</p>; return ( <> <p>你好 {user}! </p> <button onClick={() => signOut(() => navigate("/"))}>退出</button> </> ); }; const Layout = () => { return ( <div> <AuthStatus /> <ul> <li> <Link to="/">公共頁面</Link> </li> <li> <Link to="/protected">受保護頁面</Link> </li> </ul> <Outlet /> </div> ); }; export default Layout;
import { useContext, FormEvent } from "react"; import { useNavigate, useLocation, Location } from "react-router-dom"; import { AuthContext, AuthContextType } from "../AuthProvider"; interface State extends Omit<Location, "state"> { state: { from: { pathname: string; }; }; } const useAuth = () => useContext(AuthContext); const Login = () => { let auth = useAuth(); let { signIn } = auth as AuthContextType; const { state } = useLocation() as State; let from = state.from.pathname || "/"; let navigate = useNavigate(); const handleSubmit = (event: FormEvent<HTMLFormElement>) => { event.preventDefault(); let formData = new FormData(event.currentTarget); let username = formData.get("username") as string; signIn(username, () => navigate(from, { replace: true })); }; return ( <div> <p>您必須登入才能檢視該頁面 {from}</p> <form onSubmit={handleSubmit}> <label> 使用者名稱: <input name="username" type="text" /> </label> <button type="submit">登入</button> </form> </div> ); }; export default Login;
主要就是對登入狀態進行校驗,成功則渲染子元件,否則跳轉回登入頁面
import { useContext } from "react"; import { useLocation, Navigate } from "react-router-dom"; import { AuthContext, AuthContextType } from "../AuthProvider"; const useAuth = () => useContext(AuthContext); const RequireAuth = ({ children }: { children: JSX.Element }) => { let auth = useAuth(); let { user } = auth as AuthContextType; let location = useLocation(); if (!user) return <Navigate to="/login" state={{ from: location }} replace />; return children; }; export default RequireAuth;
入口檔案沒有對路由進行懶載入優化,因為是小應用,所以實際開發還是要考慮效能優化的。
import { Routes, Route } from "react-router-dom"; import AuthProvider from "src/views/AuthProvider"; import Layout from "src/views/auth/layout"; import LoginPage from "src/views/auth/login"; import PublicPage from "src/views/auth/publicPage"; import RequireAuth from "src/views/auth/requireAuth"; import ProtectedPage from "src/views/auth/protectedPage"; const App = () => { return ( <AuthProvider> <Routes> <Route element={<Layout />}> <Route path="/" element={<PublicPage />} /> <Route path="/login" element={<LoginPage />} /> <Route path="/protected" element={ <RequireAuth> <ProtectedPage /> </RequireAuth> } /> </Route> </Routes> </AuthProvider> ); }; export default App;
到此這篇關於淺談React-router v6 實現登入驗證流程的文章就介紹到這了,更多相關React-router登入驗證內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45