iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Modern Web

雙向奔赴的websocket與冰冷的react系列 第 25

[day25]React Router 路由守衛與嵌套路由

  • 分享至 

  • xImage
  •  

路由守衛?

路由守衛的核心思想是在某些路徑訪問之前進行檢查,比如檢查用戶是否已經登入。若未登入,則可以重定向到登入頁面。

  • 假設情境:
    我們有一個「儀表板」(Dashboard)頁面,僅允許已登入用戶訪問。
    未登入用戶訪問 /dashboard 時,會被重定向到 Login 頁面。

動手做做

本次架構總共分成5個檔案

src
 |
 |--index.jsx
 |--PrivateRoute.jsx
 |--SubHome.jsx
 |--Dashboard.jsx
 |--Login
  • SubHome.jsx
    主頁面
import React from 'react';
import { Link } from 'react-router-dom';

function SubHome() {
  return (
    <div>
      <h2>歡迎來到首頁</h2>
      <p>請先進行登入。</p>
      <Link to="/login">
        <button>前往登入頁面</button>
      </Link>
    </div>
  );
}

export default SubHome;
  • Dashboard
    如有驗證過後的使用者頁面,如果你直接導入如localhose/Dashboard會被強制返回唷
import React from 'react';

function Dashboard() {
  return (
    <div>
      <h2>這是儀表板頁面</h2>
      <p>歡迎,您已成功登入!</p>
    </div>
  );
}

export default Dashboard;
  • PrivateRoute
    PrivateRoute.jsx組件用來作為路由守衛,並根據用戶是否登入來決定是否允許進入某個路由。
import React from 'react';
import { Navigate } from 'react-router-dom';

function PrivateRoute({ children, isAuthenticated }) {
    return isAuthenticated ? children : backpage();
}

export default PrivateRoute;

function backpage() {
    console.log('backpage');
    return <Navigate to="/login" />;
}

主要就是根據你的登錄是否帶有驗證,來將使用者導回登陸頁OR下一頁

  • Login
import React from 'react';
import { useNavigate } from 'react-router-dom';

function Login({ setIsAuthenticated }) {
  const navigate = useNavigate();

  const handleAuthLogin = () => {
    setIsAuthenticated(true); // 模擬認證成功
    navigate('/dashboard'); // 成功登入後導航到儀表板
  };

  const handleNoAuthLogin = () => {
    setIsAuthenticated(false); // 模擬未認證
    navigate('/dashboard'); // 嘗試進入儀表板,會被路由守衛攔截
  };

  return (
    <div>
      <h2>登入頁面</h2>
      <button onClick={handleAuthLogin}>認證登入</button>
      <br />
      <button onClick={handleNoAuthLogin}>未認證登入</button>
    </div>
  );
}

export default Login;

模擬登陸的地方

  • index
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './SubHome'; 
import Login from './Login';
import Dashboard from './Dashboard';
import PrivateRoute from './PrivateRoute';

function App() {
  const [isAuthenticated, setIsAuthenticated] = useState(false); // 模擬的登入狀態

  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/login" element={<Login setIsAuthenticated={setIsAuthenticated} />} />
        <Route
          path="/dashboard"
          element={
            <PrivateRoute isAuthenticated={isAuthenticated}>
              <Dashboard />
            </PrivateRoute>
          }
        />
      </Routes>
    </Router>
  );
}

const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

說明

主要就是index.jsx的路由設定,PrivateRoute.jsx 的路由守衛機制,Login.jsx的模擬登入邏輯。

接下來一一說明

index.jsx

  • useState 用來管理 isAuthenticated(用戶是否登入)的狀態,這個狀態會透過父子通訊讓 Login 組件中被更改,並讓PrivateRoute讀取。
  • PrivateRoute 組件被用於保護 /dashboard 路徑,確保只有通過認證的用戶可以進入這個頁面。未認證的用戶會被自動重定向回登入頁面。
<Route
  path="/dashboard"
  element={
    <PrivateRoute isAuthenticated={isAuthenticated}>
      <Dashboard />
    </PrivateRoute>
  }
/>

這樣的包裹方式,可另真正要渲染的<Dashboard />放置於PrivateRoute中,相當於他的子組件

Login.jsx

  • 通過 setIsAuthenticated 來更改父組件中的 isAuthenticated 狀態(父子通信),並將路由導致/dashboard。

PrivateRoute.jsx

  • Navigate,這個功能可使你能在程序邏輯中自動改變路徑。Link需配置於Dom上。
  • return children,他會渲染你的子組件也就是<Dashboard />
  • 所以最後再利用父子通信的方式讓indexisAuthenticated告訴PrivateRoute,來判斷要導致哪裡。

最終功能:訪問受保護的路由(如 /dashboard)時,PrivateRoute 組件會檢查用戶是否已經登入,即檢查 isAuthenticated 的值。

今天結束囉,其實也沒用甚麼特殊套件等,就是把之前所教的Router、父子通信、條件渲染三個組合在一起就能達到這個效果,很神奇吧 ~


上一篇
[day24]React Router動態路由與導航
下一篇
[day26]WebSocket 與 React 基礎:建立 WebSocket 連接
系列文
雙向奔赴的websocket與冰冷的react30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言