From 7aea49a0c95ba6c82ecc3c54e3be34a588d2ec97 Mon Sep 17 00:00:00 2001 From: hailin Date: Wed, 4 Mar 2026 05:43:58 -0800 Subject: [PATCH] =?UTF-8?q?fix(admin-web):=20=E4=BF=AE=E5=A4=8D=20AdminLay?= =?UTF-8?q?out=20=E6=B8=B2=E6=9F=93=E6=9C=9F=E9=97=B4=E8=B0=83=E7=94=A8=20?= =?UTF-8?q?router.replace=20=E5=AF=BC=E8=87=B4=20React=20#310=20=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将未登录跳转逻辑从 render 函数移至 useEffect, 避免在渲染子组件时触发父组件状态更新。 Co-Authored-By: Claude Sonnet 4.6 --- frontend/admin-web/src/layouts/AdminLayout.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/frontend/admin-web/src/layouts/AdminLayout.tsx b/frontend/admin-web/src/layouts/AdminLayout.tsx index dd213be..271661f 100644 --- a/frontend/admin-web/src/layouts/AdminLayout.tsx +++ b/frontend/admin-web/src/layouts/AdminLayout.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { usePathname, useRouter } from 'next/navigation'; import Link from 'next/link'; import { t } from '@/i18n/locales'; @@ -100,13 +100,15 @@ export const AdminLayout: React.FC<{ children: React.ReactNode }> = ({ children const { isAuthenticated, isLoading, user, logout } = useAuth(); const [collapsed, setCollapsed] = useState(false); - // 未登录 → /login - if (!isLoading && !isAuthenticated) { - router.replace('/login'); - return null; - } - // 加载中显示空白 - if (isLoading) return null; + // 未登录 → /login(必须在 useEffect 中跳转,不能在 render 期间调用 router) + useEffect(() => { + if (!isLoading && !isAuthenticated) { + router.replace('/login'); + } + }, [isLoading, isAuthenticated, router]); + + // 加载中或未登录时显示空白 + if (isLoading || !isAuthenticated) return null; // Derive activeKey from current pathname const activeKey = pathname.replace(/^\//, '') || 'dashboard';