RTK Query重复调用问题:子组件未渲染仍触发请求
问题:关闭弹窗后未渲染的子组件仍触发RTK Query请求
我有一个父组件,点击按钮会通过状态变量控制子组件的条件渲染。子组件内部用RTK Query的useGetItemsQuery获取列表数据,并在useEffect里根据返回数据的长度修改内部状态。
现在遇到的问题:点击父组件按钮后,API调用正常,弹窗也能正常弹出;但关闭弹窗后,父组件的API调用没问题,可未渲染的子组件却依然会触发RTK Query请求,需要解决这个问题。
相关代码示例
RTK Query 配置
// rtk query getItems: builder.query<IItemsResponse[], string>({ query: (itemNumber) => `/application/reassign/${itemNumber}/users`, providesTags: ["Item"], keepUnusedDataFor: 0, }), export const {useGetItemsQuery} = apiSlice;
子组件中的RTK Query调用
const { data, isLoading } = useGetItemsQuery(itemNumber);
父组件条件渲染子组件
{callModalState && ( <ItemModal setModalState={setModalState} itemNumber={itemNumber} onCancel={() => { setCallModalState(false); }} onItemSuccess={() => { setModalState(false); onApplicationSuccess; }} customToastForError={() => { setModalState(false); customToastForError; }} /> )}
子组件内部状态与useEffect
// 子组件内部状态 const [modalState, setModalState] = useState<ModalState>({ showNoItemModal: false, showModal: false, }); // 子组件中的useEffect useEffect(() => { if (data && data.length > 0) { setModalState({ ...modalState, showModal: true, showNoUsersModal: false, }); } else if (data && data.length == 0) { setModalState({ ...modalState, showModal: false, showNoItemModal: true, }); } }, [data]);
解决方案
1. 确认子组件是否真正被卸载
父组件通过callModalState && <ItemModal />的条件渲染逻辑,当callModalState设为false时,子组件应该被完全卸载。如果仍触发请求,先排查:
callModalState的状态更新是否及时、正确,比如关闭弹窗时setCallModalState(false)是否被执行- 子组件是否被其他逻辑以
display: none这类隐藏方式保留,而非真正移除DOM
2. 用skip参数控制请求触发
在子组件的RTK Query调用中添加skip参数,只有当弹窗处于显示状态时才发起请求:
// 子组件中,根据内部弹窗状态控制请求是否跳过 const { data, isLoading } = useGetItemsQuery(itemNumber, { skip: !modalState.showModal && !modalState.showNoItemModal });
这样即使子组件因意外未被卸载,也不会触发不必要的请求。
3. 调整keepUnusedDataFor配置
当前设置keepUnusedDataFor: 0会让RTK Query立即清除未使用的数据,这可能导致组件重新渲染时直接发起新请求。如果不需要立即清除缓存,可以适当调整这个值(比如设为30秒),避免重复请求。
4. 检查父组件状态更新逻辑
关闭弹窗时,确保setCallModalState(false)的逻辑没有被阻塞,且状态更新后父组件完成重新渲染,从而正确卸载子组件。可以在父组件中添加日志,验证callModalState的变化是否符合预期。
内容的提问来源于stack exchange,提问作者Magnanamous
相关产品推荐
相关产品推荐

