Files
gongxue-base/apps/admin/src/components/DefaultRoute.tsx
wangziqi ce9bde35eb
Some checks failed
CI / check (pull_request) Failing after 2m14s
fix(admin): 修复首次进入系统后点击任意导航被拉回 dashboard
根因:RouteKeeper 保活缓存了首页 index 节点,DefaultRoute 中的声明式
<Navigate> 会随缓存节点在后续路由变化时反复触发 replace,导致所有导航
被强制拉回落地页(dashboard),刷新后因不再经过 / 而恢复正常。

修复:DefaultRoute 改为 effect 导航,仅在确实处于 / 且已算出落地页时
跳转一次;navigate 通过 ref 持有避免 effect 空转。新增集成测试覆盖
「首次进入 / → 跳转一次 → 后续导航不被劫持 → 回到 / 仍能重定向」。
2026-08-10 09:42:46 +08:00

39 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useRef } from 'react';
import { useLocation, useNavigate } from 'react-router';
import { Result, Spin } from 'antd';
import { usePermission } from '../hooks/usePermission';
import { findRoleAwareLandingPath } from '../auth/menu-policy';
import { useUserStore } from '../store/user/userStore';
const DefaultRoute: React.FC = () => {
const { permissions, permissionsReady } = usePermission();
const roles = useUserStore((state) => state.user?.roles ?? []);
const navigate = useNavigate();
const { pathname } = useLocation();
const firstPath = permissionsReady ? findRoleAwareLandingPath(roles, permissions) : null;
// 用 effect 导航替代声明式 <Navigate>RouteKeeper 会把首页index节点保活缓存
// 声明式 <Navigate> 在缓存节点随路由变化重渲染时会反复触发,导致首次进入系统后
// 点击任何按钮都被拉回 dashboard必须刷新页面才能恢复。这里仅在确实处于首页
// 且已计算出落点时跳转navigate 通过 ref 持有,避免其每次渲染变化导致 effect 空转。
const navigateRef = useRef(navigate);
navigateRef.current = navigate;
useEffect(() => {
if (pathname === '/' && firstPath) {
navigateRef.current(firstPath, { replace: true });
}
}, [pathname, firstPath]);
if (!permissionsReady) {
return <Spin size="large" style={{ display: 'block', margin: '80px auto' }} />;
}
if (!firstPath) {
return (
<Result status="403" title="暂无可访问功能" subTitle="请联系管理员为当前账号分配功能权限" />
);
}
return null;
};
export default DefaultRoute;