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 <noreply@anthropic.com>
This commit is contained in:
parent
f84e8b4700
commit
1d7d38a82c
|
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
import { useAppDispatch, useAppSelector } from '@/store/hooks';
|
||||||
import { getProfile } from '@/store/slices/auth.slice';
|
import { getProfile } from '@/store/slices/auth.slice';
|
||||||
|
|
@ -15,17 +15,34 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { token, isAuthenticated, user } = useAppSelector((state) => state.auth);
|
const { token, isAuthenticated, user } = useAppSelector((state) => state.auth);
|
||||||
const { isCollapsed } = useSidebar();
|
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(() => {
|
useEffect(() => {
|
||||||
if (!token) {
|
if (isInitialized && token && !user) {
|
||||||
router.push('/login');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
dispatch(getProfile());
|
dispatch(getProfile());
|
||||||
}
|
}
|
||||||
}, [token, user, dispatch, router]);
|
}, [isInitialized, token, user, dispatch]);
|
||||||
|
|
||||||
|
// 等待初始化完成
|
||||||
|
if (!isInitialized) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-screen items-center justify-center">
|
||||||
|
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue