React Query调用refetch时数据/错误未失效,新数据叠加问题求助
React Query 5.52.2中refetch时旧数据/错误未清除导致叠加显示的解决方案
问题描述
使用@tanstack/react-query 5.52.2版本时,点击按钮触发refetch获取数据,之前的data和error变量在渲染过程中不会被清除,导致新数据与旧状态叠加显示。
原组件代码
import { useQuery } from "@tanstack/react-query"; import React from "react"; import { mockAPICall } from "./helper/mockAPICall"; const FetchQuery = () => { const { data, error, refetch, isFetching } = useQuery({ queryKey: ["repoData"], queryFn: mockAPICall, enabled: false, retry: false, }); const clicked = () => { refetch(); }; return ( <div> <button className="flex m-auto border-solid border-black px-7 py-3 border-2 hover:border-gray-400 active:text-gray-400" onClick={clicked} > React Query </button> <div className="py-3 flex m-auto justify-center"> {isFetching && ( <div className="text-slate-400">{"Loading..."}</div> )} {data && <div className="text-green-500">{data}</div>} {error && <div className="text-red-500">{error}</div>} </div> </div> ); }; export default FetchQuery;
Mock API代码
export const mockAPICall = () => { const randomNum = Math.floor(Math.random() * (100 - 0)); console.log("🚀 > mockAPICall > randomNum:", randomNum); return new Promise((res, rej) => { setTimeout(() => { if (randomNum < 50) { res("Successful Response "+ randomNum); console.log("success"); } else { rej("Intended Err "+ randomNum); console.log("fail"); } }, 1000); }); };
问题原因
React Query默认保留旧的data和error状态直到新请求完成,目的是避免页面闪烁。但原代码中,当isFetching为true时,会同时渲染Loading提示与旧的data/error,导致叠加显示。
解决方案
修改渲染逻辑,在请求进行中(isFetching为true)时,仅显示Loading提示,隐藏旧状态:
<div className="py-3 flex m-auto justify-center"> {isFetching ? ( <div className="text-slate-400">Loading...</div> ) : ( <> {data && <div className="text-green-500">{data}</div>} {error && <div className="text-red-500">{error}</div>} </> )} </div>
修改后的完整组件代码
import { useQuery } from "@tanstack/react-query"; import React from "react"; import { mockAPICall } from "./helper/mockAPICall"; const FetchQuery = () => { const { data, error, refetch, isFetching } = useQuery({ queryKey: ["repoData"], queryFn: mockAPICall, enabled: false, retry: false, }); const clicked = () => { refetch(); }; return ( <div> <button className="flex m-auto border-solid border-black px-7 py-3 border-2 hover:border-gray-400 active:text-gray-400" onClick={clicked} > React Query </button> <div className="py-3 flex m-auto justify-center"> {isFetching ? ( <div className="text-slate-400">Loading...</div> ) : ( <> {data && <div className="text-green-500">{data}</div>} {error && <div className="text-red-500">{error}</div>} </> )} </div> </div> ); }; export default FetchQuery;
其他可选方案
- 使用
queryClient.invalidateQueries替代refetch,强制使缓存失效并重新获取数据(需导入useQueryClient):import { useQueryClient, useQuery } from "@tanstack/react-query"; const queryClient = useQueryClient(); const clicked = () => { queryClient.invalidateQueries({ queryKey: ["repoData"] }); };
内容的提问来源于stack exchange,提问作者Jaydeep Godhani
相关产品推荐
相关产品推荐

