把 Token 丟去 /auth/verify 只是「確認他是不是合法使用者」,但接下來還有兩件事要處理:
這一節會用 React 最常見的做法:AuthContext + ProtectedRoute 組合拳
不需要上 Redux、不用引入額外套件,小專案、中型應用都適用。
import { createContext, useContext, useState, useEffect } from "react";
import { useVerifyToken } from "../hooks/useVerifyToken";
const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
  const { verifyToken } = useVerifyToken();
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  // 初始化時就驗證一次
  useEffect(() => {
    const checkToken = async () => {
      try {
        const data = await verifyToken();
        setUser(data); // { uid, email ... }
      } catch {
        setUser(null);
      } finally {
        setLoading(false);
      }
    };
    checkToken();
  }, []);
  return (
    <AuthContext.Provider value={{ user, loading, setUser }}>
      {children}
    </AuthContext.Provider>
  );
};
export const useAuth = () => useContext(AuthContext);
這樣做的好處是:
✅ App 一載入就會自動驗證 Token
✅ 驗證結果會存起來、不會重複打 API
✅ 之後要登出或重新驗證也方便
import { Navigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
export default function ProtectedRoute({ children }) {
  const { user, loading } = useAuth();
  if (loading) return <p>驗證中...</p>;
  return user ? children : <Navigate to="/login" replace />;
}
import { Routes, Route } from "react-router-dom";
import ProtectedRoute from "./components/ProtectedRoute";
import Dashboard from "./pages/Dashboard";
import Login from "./pages/Login";
export default function AppRoutes() {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <Route
        path="/dashboard"
        element={
          <ProtectedRoute>
            <Dashboard />
          </ProtectedRoute>
        }
      />
    </Routes>
  );
}
import ReactDOM from "react-dom/client";
import AppRoutes from "./App";
import { AuthProvider } from "./contexts/AuthContext";
ReactDOM.createRoot(document.getElementById("root")).render(
  <AuthProvider>
    <AppRoutes />
  </AuthProvider>
);