diff --git a/src/api/user.ts b/src/api/user.ts index f65fe44..946ecef 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -5,6 +5,10 @@ export const getProfile = async (): Promise => { return fetcher(FetcherMethod.GET, '/api/v1/profile', null) } +export const refreshToken = async (): Promise => { + return fetcher(FetcherMethod.GET, '/api/v1/refresh_token', null) +} + export const login = async (username: string, password: string): Promise => { return fetcher(FetcherMethod.POST, '/api/v1/login', { username, password }) } diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index 047028b..5d48676 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -1,8 +1,8 @@ -import { createContext, useContext, useEffect, useMemo, useState } from "react"; +import { createContext, useContext, useEffect, useMemo, useRef } from "react"; import { useNavigate } from "react-router-dom"; import { useMainStore } from "./useMainStore"; import { AuthContextProps } from "@/types"; -import { getProfile, login as loginRequest } from "@/api/user"; +import { getProfile, login as loginRequest, refreshToken } from "@/api/user"; import { toast } from "sonner"; const AuthContext = createContext({ @@ -16,23 +16,34 @@ export const AuthProvider = ({ children }: { }) => { const profile = useMainStore(store => store.profile) const setProfile = useMainStore(store => store.setProfile) - const [lastUpdatedAt, setLastUpdatedAt] = useState(0); + const initialized = useRef(false) + const lastRefreshedAt = useRef(0) - // FIXME @naiba 触发了两次 useEffect(() => { - if (profile && Date.now() - lastUpdatedAt > 1000 * 60 * 5) { - console.log(profile, Date.now(), lastUpdatedAt) - getProfile().then((data) => { - setLastUpdatedAt(Date.now()) - if (data && data.username !== profile.username) { - console.log('bingo', data.username); - setProfile(data) - } - }).catch(() => { - setLastUpdatedAt(Date.now()) - setProfile(undefined) - }) + if (initialized.current) { + return } + initialized.current = true; + (async () => { + while (true) { + if (!profile) { + await new Promise((resolve) => setTimeout(resolve, 1000)) + continue + } + if (lastRefreshedAt.current + 1000 * 60 * 10 > Date.now()) { + await new Promise((resolve) => setTimeout(resolve, 1000)) + continue + } + try { + await refreshToken(); + const user = await getProfile(); + setProfile(user); + lastRefreshedAt.current = Date.now(); + } catch (error) { + setProfile(undefined); + } + } + })(); }, [profile]) const navigate = useNavigate(); diff --git a/src/main.tsx b/src/main.tsx index e0bba94..a0f1313 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -15,7 +15,7 @@ import { AuthProvider } from './hooks/useAuth'; const router = createBrowserRouter([ { - path: "/dashboard/", + path: "/dashboard", element: , errorElement: , children: [ diff --git a/src/routes/login.tsx b/src/routes/login.tsx index 9f46f87..2573b2a 100644 --- a/src/routes/login.tsx +++ b/src/routes/login.tsx @@ -66,7 +66,7 @@ export default () => { Password - + This is your public display name. @@ -75,7 +75,7 @@ export default () => { )} /> - + diff --git a/src/routes/protect.tsx b/src/routes/protect.tsx index 1c0952f..eae86dd 100644 --- a/src/routes/protect.tsx +++ b/src/routes/protect.tsx @@ -7,7 +7,7 @@ export const ProtectedRoute = ({ children }: { const { profile } = useAuth(); if (!profile && window.location.pathname !== "/dashboard/login") { - return ; + return <>{children}; } return children;