diff --git a/web/src/auth/AuthContext.tsx b/web/src/auth/AuthContext.tsx index 2eb0be4..45068a5 100644 --- a/web/src/auth/AuthContext.tsx +++ b/web/src/auth/AuthContext.tsx @@ -26,7 +26,10 @@ export function AuthProvider({ children }: { children: ReactNode }) { const meQ = useQuery({ queryKey: ["me"], queryFn: api.me, enabled: !!token, retry: 0 }); useEffect(() => { - if (token && meQ.isError) setTok(null); + if (token && meQ.isError) { + setToken(null); // 非 401 失败也要清持久化 token,避免与 React 状态分叉导致 RequireAuth 永久加载 + setTok(null); + } }, [token, meQ.isError]); const value = useMemo( diff --git a/web/src/pages/Login.tsx b/web/src/pages/Login.tsx index fda8468..5402644 100644 --- a/web/src/pages/Login.tsx +++ b/web/src/pages/Login.tsx @@ -1,5 +1,5 @@ import { useState, type FormEvent } from "react"; -import { Navigate, useLocation, useNavigate } from "react-router-dom"; +import { Navigate, useLocation } from "react-router-dom"; import { useAuth } from "../auth/AuthContext"; import { toast } from "../components/Toaster"; import { btnPrimary, card, input } from "../components/ui"; @@ -7,7 +7,6 @@ import { btnPrimary, card, input } from "../components/ui"; export default function Login() { const { login, user } = useAuth(); const loc = useLocation() as { state?: { from?: string } }; - const nav = useNavigate(); const [u, setU] = useState(""); const [p, setP] = useState(""); const [busy, setBusy] = useState(false); @@ -19,7 +18,6 @@ export default function Login() { setBusy(true); try { await login(u, p); - nav("/", { replace: true }); } catch (err) { toast("err", err instanceof Error ? err.message : "登录失败"); } finally {