React Router Loader结合RTK Query:重验证时等待查询完成异常
问题分析
你遇到的核心问题是:执行带invalidatesTags的mutation后调用revalidate(),loader会在invalidatesTags触发的自动重取查询仍处于pending状态时就执行。而getRunningQueriesThunk返回空数组,是因为该方法默认仅返回当前组件上下文订阅的正在运行的查询,invalidatesTags触发的后台重取查询不在默认筛选范围内。
解决方案
1. 给getRunningQueriesThunk指定筛选条件
通过传入筛选函数,匹配你需要等待的查询(比如getBook),这样就能捕获到invalidatesTags触发的重取请求:
export const loader = ({ dispatch, state }) => async ({ params }) => { console.log(state.api) // 等待所有endpointName为getBook的正在运行的查询 await Promise.all( dispatch(api.util.getRunningQueriesThunk(query => query.endpointName === 'getBook')) ) try { const promise = dispatch(api.endpoints.getBook(params.id)) const response = await promise.unwrap(); return { layoutTitle: response.title } } finally { promise.unsubscribe() } }
2. 精准等待指定查询完成
使用waitForQuery方法直接等待目标查询完成,比getRunningQueriesThunk更精准,适合在组件中控制revalidate时机:
export const Page = () => { const { data } = useGetBookQuery(); const [update] = useUpdateBookMutation(); const revalidator = useRevalidator(); const params = useParams(); const handleUpdate = async () => { const updatePromise = update(); await updatePromise.unwrap(); // 等待getBook查询完成(替换成你的查询参数) await dispatch(api.util.waitForQuery('getBook', params.id)); revalidator.revalidate(); } return ( <div> <button onClick={handleUpdate}> update </button> </div> ) }
3. 让Loader直接依赖RTK Query缓存状态
无需重新dispatch查询,直接从缓存读取数据,若缓存正在更新则等待完成,确保Loader拿到最新数据:
export const loader = ({ dispatch, state }) => async ({ params }) => { const bookQuery = api.endpoints.getBook.select(params.id)(state); // 缓存正在更新,等待完成 if (bookQuery.status === 'pending') { await dispatch(api.util.waitForQuery('getBook', params.id)); const updatedQuery = api.endpoints.getBook.select(params.id)(state); return { layoutTitle: updatedQuery.data.title }; } // 缓存已有数据,直接返回 if (bookQuery.status === 'fulfilled') { return { layoutTitle: bookQuery.data.title }; } // 缓存为空,触发查询并等待 try { const promise = dispatch(api.endpoints.getBook(params.id)); const response = await promise.unwrap(); return { layoutTitle: response.title }; } finally { promise.unsubscribe(); } }
代码错误修正
- 修正
cont response为const response - 补全
dispatch(endpoint.getBook(...)的闭合括号
内容的提问来源于stack exchange,提问作者Mahmoud Ashraf
相关产品推荐
相关产品推荐

