React-Query调用setQueryData未更新缓存,正确的缓存更新方式是什么
问题原因
- 你把
QueryClient实例化写在了App组件内部,组件每一次重渲染都会生成全新的QueryClient实例,之前的缓存和你做的缓存更新操作都会被清空,自然拿不到更新后的数据。 useQuery返回的data是当前渲染周期的快照值,你在onSuccess回调里修改缓存后,本次渲染的data不会立刻变更,要等缓存更新触发组件重渲染后,下一次渲染拿到的data才是更新后的值。- 你没有用
QueryClientProvider包裹应用,useQuery默认无法拿到你定义的QueryClient实例,缓存操作自然不会生效。
正确实现方式
核心原则
保证 QueryClient 实例全局唯一,不要每次组件渲染都生成新实例,同时通过 QueryClientProvider 全局传递实例。你的 setQueryData 语法本身没有问题,只要作用在同一个实例上即可生效。
完整示例代码
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query' // 实例放在组件外部,保证全局唯一 const queryClient = new QueryClient() // 替换为你自己的请求方法 const fetcher = () => fetch('/api/repo').then(res => res.json()) function App() { const { isLoading, error, data } = useQuery({ queryKey: ['repoData'], queryFn: fetcher, onSuccess: () => { // 手动更新缓存为指定值 queryClient.setQueryData(['repoData'], []) } }) // 第一次打印是fetcher返回的原始数据,缓存更新触发重渲染后第二次打印为空数组 console.log('data', data) return ( <QueryClientProvider client={queryClient}> <div className="App"> <Home /> </div> </QueryClientProvider> ); }
简化方案
如果你只是需要统一把当前接口的返回值转为空数组,不需要额外手动操作缓存,可以直接用 select 配置项简化代码:
const { isLoading, error, data } = useQuery({ queryKey: ['repoData'], queryFn: fetcher, // 直接转换返回值,不需要操作缓存 select: () => [] })
内容的提问来源于stack exchange,提问作者Ramiro Herrera
相关产品推荐
相关产品推荐

