From 1d7d38a82c0b757eb38123bff81f9e054379a839 Mon Sep 17 00:00:00 2001 From: hailin Date: Tue, 13 Jan 2026 00:25:59 -0800 Subject: [PATCH] fix(frontend): prevent redirect to dashboard on page refresh Fix hydration race condition where token check happened before localStorage was read. Now waits for client-side initialization before deciding whether to redirect to login. Co-Authored-By: Claude Opus 4.5 --- .../src/app/(dashboard)/layout.tsx | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/frontend/mining-admin-web/src/app/(dashboard)/layout.tsx b/frontend/mining-admin-web/src/app/(dashboard)/layout.tsx index 474ef53c..cefc97f2 100644 --- a/frontend/mining-admin-web/src/app/(dashboard)/layout.tsx +++ b/frontend/mining-admin-web/src/app/(dashboard)/layout.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { useAppDispatch, useAppSelector } from '@/store/hooks'; import { getProfile } from '@/store/slices/auth.slice'; @@ -15,17 +15,34 @@ export default function DashboardLayout({ children }: { children: React.ReactNod const dispatch = useAppDispatch(); const { token, isAuthenticated, user } = useAppSelector((state) => state.auth); const { isCollapsed } = useSidebar(); + const [isInitialized, setIsInitialized] = useState(false); + + // 等待客户端 hydration 完成后再检查 token + useEffect(() => { + // 在客户端检查 localStorage 中是否有 token + const storedToken = localStorage.getItem('admin_token'); + if (!storedToken) { + // 确实没有 token,跳转到登录页 + router.push('/login'); + } else { + setIsInitialized(true); + } + }, [router]); useEffect(() => { - if (!token) { - router.push('/login'); - return; - } - - if (!user) { + if (isInitialized && token && !user) { dispatch(getProfile()); } - }, [token, user, dispatch, router]); + }, [isInitialized, token, user, dispatch]); + + // 等待初始化完成 + if (!isInitialized) { + return ( +
+ +
+ ); + } if (!token) { return null;