如何用RTK Query执行单次请求且无需订阅缓存更新?
关于RTK Query单次请求且无需缓存订阅的最简实现方法
你需要在RTK Query中执行单次请求,同时获取isLoading/error等元属性,且不订阅后续的缓存更新,同时觉得现有方法过于繁琐。
现有方法的问题
- 方法1:需要手动维护加载、错误和数据状态,代码冗余
export const App = () => { const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const [user, setUser] = useState(null); const [trigger] = useLazyGetUserQuery(); useEffect(() => { async function fetch() { try{ const response = await trigger().unwrap(); setUser(response.data); } catch(error) { setError(error) } finally { setLoading(false); } } fetch(); }, [trigger]); // do something with error/loading/data here...
- 方法2:设置
skip后,data/error会变为undefined,必须手动将数据存入本地状态
export const App = () => { const [user, setUser] = useState(null); const { isUninitialized, isLoading, data, error } = useGetUserQuery(undefined, { skip: user !== null }); useEffect(() => { if(data) setUser(data.user); }, [data]);
实现你期望的简洁方案
可以自己封装一个自定义Hook,实现类似useGetUserQueryOnce的效果,既不用手动维护状态,也不会丢失数据:
自定义Hook封装
import { useState, useEffect } from 'react'; // 替换为你的API slice导出的useLazyGetUserQuery import { useLazyGetUserQuery } from './api/userApi'; export const useGetUserQueryOnce = () => { const [trigger, result] = useLazyGetUserQuery(); const [finalData, setFinalData] = useState(null); const [finalError, setFinalError] = useState(null); const [isLoading, setIsLoading] = useState(true); useEffect(() => { let isMounted = true; const fetchData = async () => { try { const response = await trigger().unwrap(); if (isMounted) { setFinalData(response.data); } } catch (err) { if (isMounted) { setFinalError(err); } } finally { if (isMounted) { setIsLoading(false); } } }; fetchData(); // 组件卸载时取消状态更新 return () => { isMounted = false; }; }, [trigger]); return { isLoading, error: finalError, data: finalData, // 可按需暴露RTK Query返回的其他元属性,比如isSuccess isSuccess: !!finalData && !finalError }; };
使用方式
export const App = () => { const { isLoading, error, data } = useGetUserQueryOnce(); if (isLoading) return <div>加载中...</div>; if (error) return <div>请求出错:{error.message}</div>; if (data) return <div>用户名称:{data.name}</div>; return null; };
这个自定义Hook的优势:
- 自动处理
isLoading/error/data状态,无需手动维护 - 请求完成后不再订阅缓存更新,数据存在本地state中,不会受后续缓存变化影响
- 代码简洁,调用方式完全符合你的预期
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

