如何用react-query正确处理返回not_modified的API缓存逻辑?
React Query 处理带 ifModifiedSince 的 API 响应
你的核心问题在于两点:一是查询函数错误依赖了 useQuery 返回的 data(该值在查询执行时可能未更新),二是遇到 not_modified 响应时,无法正确获取缓存中的有效旧数据(此时缓存已被新的空响应覆盖)。以下是正确的实现方式:
1. 修复查询函数:从缓存读取 lastModified
不要直接使用 useQuery 返回的 data,而是通过 queryClient 直接读取缓存中的最新有效数据,确保每次请求都能传递正确的 ifModifiedSince 参数。
2. 处理 not_modified 响应:保留旧数据
在查询流程中拦截 not_modified 响应,返回缓存中的有效数据,避免缓存被空响应覆盖。
完整代码示例
import { useQuery, QueryClient } from '@tanstack/react-query'; // 定义类型(根据实际场景调整) type TodoItem = { userId: number; id: number; title: string; completed: boolean }; type GetTodosOkResponse = { status: 'ok'; todos: TodoItem[]; lastModified: string }; type GetTodosNotModifiedResponse = { status: 'not_modified' }; type GetTodosResponse = GetTodosOkResponse | GetTodosNotModifiedResponse; const todosQueryKey = ['todos']; export const useTodos = (queryClient: QueryClient) => { return useQuery({ queryKey: todosQueryKey, queryFn: async () => { // 从缓存获取上次的有效修改时间 const cachedValidData = queryClient.getQueryData<GetTodosOkResponse>(todosQueryKey); const lastModified = cachedValidData?.lastModified || ''; const response = await getTodos({ ifModifiedSince: lastModified }); // 若返回未修改,直接返回缓存的有效数据(无缓存则返回原响应) if (response.status === 'not_modified') { return cachedValidData || response; } return response; }, select: (data): GetTodosOkResponse | undefined => { if (!data || data.status === 'not_modified') return undefined; // 排序时创建新数组,避免原地修改缓存原始数据 const sortedTodos = [...data.todos].sort((a, b) => b.id - a.id); return { ...data, todos: sortedTodos }; }, refetchInterval: 5000, staleTime: Infinity, // 确保重查时始终保留之前的有效数据 keepPreviousData: true, }); };
关键细节说明
- 缓存读取逻辑:通过
queryClient.getQueryData获取缓存中的有效数据,保证每次请求的ifModifiedSince参数都是最新的修改时间。 not_modified响应处理:在查询函数内直接返回缓存数据,避免 React Query 用空响应覆盖缓存,后续select可直接处理有效数据。- 不可变排序:使用
[...data.todos]创建新数组后再排序,符合 React 状态管理的不可变性原则,避免意外修改缓存数据。 - 状态稳定性:
keepPreviousData: true确保重查过程中组件始终能拿到之前的有效数据,不会出现空白或闪烁。
内容的提问来源于stack exchange,提问作者Fedorov7890
相关产品推荐
相关产品推荐

