如何配置react-query仅在查询失效时发起数据请求?
React Query实现“仅查询失效时发起请求”的方案
核心思路
React Query没有直接提供“仅在查询失效时请求”的单一配置项,但可以通过**enabled选项** + 缓存数据复用的组合,实现你要的“一次性加载全量数据,子查询仅在失效时重取”的需求。
具体实现步骤
1. 加载全量Todos并缓存
在根组件或父组件中,用主查询键['load', 'todos']加载所有待办事项,确保数据存入React Query缓存:
const { data: allTodosData } = useQuery({ queryKey: ['load', 'todos'], queryFn: () => fetchAllTodos(), // 全量Todos的请求函数 staleTime: Infinity, // 让全量数据默认保持新鲜,避免自动重新请求 });
2. 子组件单个Todo查询的配置
子组件中使用['load', 'todo', todoId]作为查询键,通过以下配置实现“仅失效时请求”:
import { useQuery, useQueryClient } from '@tanstack/react-query'; const TodoItem = ({ todoId }) => { const queryClient = useQueryClient(); const { data: todo } = useQuery({ queryKey: ['load', 'todo', todoId], queryFn: () => fetchSingleTodo(todoId), // 单个Todo的请求函数 // 从全量Todos缓存中获取初始数据 initialData: () => { const allTodos = queryClient.getQueryData(['load', 'todos']); return allTodos?.todos.find(item => item.id === todoId); }, // 控制查询是否自动执行:只有当初始数据不存在,或查询被标记为失效时才发起请求 enabled: () => { const hasInitialData = !!queryClient.getQueryData(['load', 'todos'])?.todos.find(item => item.id === todoId); const queryState = queryClient.getQueryState(['load', 'todo', todoId]); // 两种情况触发请求:1. 没有初始数据;2. 查询已失效且未处于空闲状态 return !hasInitialData || (queryState?.status === 'stale' && queryState.fetchStatus !== 'idle'); }, // 初始数据默认永久新鲜,直到手动标记失效 staleTime: Infinity, }); if (!todo) return <div>Loading...</div>; return <div>{todo.label}</div>; };
3. 手动标记查询失效
当某个Todo需要更新时,调用invalidateQueries标记对应子查询失效,触发重新请求:
// 比如在更新Todo后执行 queryClient.invalidateQueries({ queryKey: ['load', 'todo', todoId] });
关键说明
initialData从全量缓存中取数,避免子组件初始时发起多余请求;enabled选项是核心:通过判断初始数据是否存在、查询状态是否失效,精准控制请求时机;staleTime: Infinity确保初始数据不会被自动标记为失效,只有手动调用invalidateQueries才会触发重取,完全符合“按需失效重取”的需求。
内容的提问来源于stack exchange,提问作者SeDav
相关产品推荐
相关产品推荐

