fix(web): recover route errors on scope change
This commit is contained in:
@@ -58,4 +58,29 @@ describe('route recovery boundary', () => {
|
||||
expect(screen.getByText('本地状态 1')).toBeInTheDocument();
|
||||
expect(mounts).toBe(1);
|
||||
});
|
||||
|
||||
it('retries a failed route when its search scope changes without remounting healthy scopes', () => {
|
||||
vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
let healthyMounts = 0;
|
||||
function ScopeSensitivePage() {
|
||||
const [params] = useSearchParams();
|
||||
if (params.get('scope') === 'broken') throw new Error('invalid route scope');
|
||||
useEffect(() => { healthyMounts += 1; }, []);
|
||||
return <strong>新筛选范围已恢复</strong>;
|
||||
}
|
||||
function RecoveryHarness() {
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
return <><button type="button" onClick={() => setSearchParams({ scope: 'healthy' })}>修正筛选条件</button><RoutePage page={ScopeSensitivePage} label="告警中心" /></>;
|
||||
}
|
||||
|
||||
render(<MemoryRouter future={ROUTER_FUTURE} initialEntries={['/alerts?scope=broken']}><RecoveryHarness /></MemoryRouter>);
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('当前模块暂时无法显示');
|
||||
expect(screen.getByText(/更换筛选条件会自动重试/)).toBeInTheDocument();
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '修正筛选条件' }));
|
||||
|
||||
expect(screen.queryByRole('alert')).not.toBeInTheDocument();
|
||||
expect(screen.getByText('新筛选范围已恢复')).toBeInTheDocument();
|
||||
expect(healthyMounts).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,6 +42,12 @@ class RecoverableRouteBoundary extends Component<{ children: ReactNode; routeKey
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(previous: Readonly<{ children: ReactNode; routeKey: string }>) {
|
||||
if (this.state.error && previous.routeKey !== this.props.routeKey) {
|
||||
this.setState({ error: undefined });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { error } = this.state;
|
||||
if (!error) return this.props.children;
|
||||
@@ -51,7 +57,7 @@ class RecoverableRouteBoundary extends Component<{ children: ReactNode; routeKey
|
||||
<div>
|
||||
<small>{chunkError ? '检测到页面版本更新' : '页面运行异常'}</small>
|
||||
<h2>{chunkError ? '正在等待加载最新页面资源' : '当前模块暂时无法显示'}</h2>
|
||||
<p>{chunkError ? '通常是发布后旧标签页仍引用上一版本资源。刷新后会恢复,不会丢失服务端数据。' : '页面已被安全隔离,侧栏和其他模块仍可使用。可刷新当前页面重试。'}</p>
|
||||
<p>{chunkError ? '通常是发布后旧标签页仍引用上一版本资源。刷新后会恢复,不会丢失服务端数据。' : '页面已被安全隔离,侧栏和其他模块仍可使用。更换筛选条件会自动重试,也可刷新当前页面。'}</p>
|
||||
<code>{error.message || error.name}</code>
|
||||
<footer>
|
||||
<button type="button" onClick={() => window.location.reload()}><IconRefresh />刷新当前页面</button>
|
||||
|
||||
Reference in New Issue
Block a user