InvalidateQueries执行时机错误,如何正确刷新useQuery数据?
const { isLoading, error, data } = useQuery(["click"], () => makeRequest.get("/example/1234").then((res) => { return res.data; }) ); const Path = async (postId, cardNickNameId) => { const promise = async () => { try { const res = await makeRequest.post("/elpmaxe", { postId: postId, cardNickNameId: cardNickNameId, }); queryClient.invalidateQueries(["click"]); //<------ BAD! console.log(res); return Promise.resolve(res.data); } catch (error) { console.log(error); return Promise.reject(error.res.data); } }; const success = PromisseSucess("Assinando com sucesso!").success; //prettier-ignore const pending = PromisseLoading("Subscribing you to the best plan.").pending; //prettier-ignore const error = PromisseError("You need add a payment method or choose a card!").error; const toastOptions = { success, pending, error, }; toast.promise(promise, toastOptions); };
问题核心
你遇到的问题是POST请求返回时,后端可能还没完成数据持久化,此时立即调用invalidateQueries触发的GET请求会拿到旧数据,setTimeout只是临时规避,并非合理方案。
正确解决方案
方案1:等待invalidateQueries执行完成
invalidateQueries返回Promise,通过await等待它完成,确保refetch操作执行完毕:
const res = await makeRequest.post("/elpmaxe", { postId: postId, cardNickNameId: cardNickNameId, }); // 等待失效和refetch完成 await queryClient.invalidateQueries(["click"]); console.log(res); return Promise.resolve(res.data);
这个方案适用于后端保证POST响应返回时数据已写入数据库的场景,确保GET请求能拿到最新数据。
方案2:乐观更新+缓存失效
如果希望用户立即看到更新效果,同时后台同步最新数据,可以先手动更新缓存,再执行失效操作:
const res = await makeRequest.post("/elpmaxe", { postId: postId, cardNickNameId: cardNickNameId, }); // 根据POST结果手动更新缓存(需根据实际数据结构调整) queryClient.setQueryData(["click"], (oldData) => { // 示例:添加新数据或修改现有条目 return { ...oldData, // 插入或更新对应字段 }; }); // 失效查询,后台获取最新数据 await queryClient.invalidateQueries(["click"]);
方案3:改用useMutation(推荐)
React Query的useMutation专门处理修改类请求,其生命周期钩子能更可靠地处理缓存失效:
// 定义mutation const mutation = useMutation( ({ postId, cardNickNameId }) => makeRequest.post("/elpmaxe", { postId, cardNickNameId }), { onSuccess: () => { // 确保POST成功后才失效查询 queryClient.invalidateQueries(["click"]); }, onError: (error) => console.log(error), } ); // 重构Path函数 const Path = (postId, cardNickNameId) => { mutation.mutate({ postId, cardNickNameId }, { onSuccess: () => toast.success("Assinando com sucesso!"), onPending: () => toast.loading("Subscribing you to the best plan."), onError: () => toast.error("You need add a payment method or choose a card!"), }); };
useMutation会自动处理异步流程,确保只有当POST请求成功完成后,才执行invalidateQueries,彻底避免时序问题。
内容的提问来源于stack exchange,提问作者Rodrigo Carvalho
相关产品推荐
相关产品推荐

