React Error Boundary未捕获错误:react-query+Suspense使用问题排查
问题分析与解决
你的ErrorBoundary无法捕获错误的核心原因是:useQuery的调用位置在ErrorBoundary和QueryErrorResetBoundary的包裹范围之外。
React的ErrorBoundary只能捕获其子组件树渲染过程中抛出的错误。你当前在WorkHistory组件的顶层直接调用了mockApi.getWorkHistory(本质是执行useQuery),当suspense: true时,查询的错误会在组件初始化渲染阶段直接抛出,此时ErrorBoundary还未完成对该逻辑的包裹,导致错误逃逸到全局,无法被捕获。
修复方案
将useQuery的调用逻辑移到ErrorBoundary内部的子组件中,确保错误发生在ErrorBoundary的包裹范围内:
1. 拆分出内容子组件
// 新增子组件,在内部调用useQuery const WorkHistoryContent = () => { const { caseId } = useContext(); const { api: mockApi } = useMockApi(); const { data: workHistory } = mockApi.getWorkHistory(caseId.toString()); return <WorkHistory workHistory={workHistory} />; };
2. 修改原组件结构
export const WorkHistory = () => { return ( <QueryErrorResetBoundary> {({ reset }) => ( <ErrorBoundary fallbackRender={({ error, resetErrorBoundary }) => ( <div> There was an error! <Button onClick={() => resetErrorBoundary()}>Try again</Button> <pre style={{ whiteSpace: "normal" }}>{error.message}</pre> </div> )} onReset={reset} > <Suspense fallback={ <div className="flex justify-center"> <Loader size="3xlarge" title="Loading..." /> </div> } > {/* 渲染内部子组件,useQuery在这里执行 */} <WorkHistoryContent /> </Suspense> </ErrorBoundary> )} </QueryErrorResetBoundary> ); };
额外优化:修正QueryKey
当前你的queryKey是固定字符串workHistory,当caseId变化时,React Query不会重新发起查询。建议将caseId加入queryKey,保证查询的唯一性:
const getWorkHistory = (caseId: string) => useQuery({ queryKey: ['workHistory', caseId], // 加入caseId作为key的一部分 queryFn: (): Promise<WorkHistoryDto[]> => fakeFetch(JSON.parse(localStorage.getItem(`workHistory`))), staleTime: Infinity, suspense: true, });
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

