React-Query分页场景下getQueryData与setQueryData的使用问题
解决React Query分页场景下删除条目更新缓存的问题
这个问题我之前做项目的时候也碰到过,分页之后QueryKey带上了页码参数,原来直接用'todos'作为键获取缓存的逻辑就失效了,给你几个实用的解决思路,你可以根据自己的场景选:
1. 精准更新目标分页的缓存(已知被删条目所在页码)
如果删除操作时你能拿到被删todo所在的页码(比如当前页面的todo,或者通过id计算出页码),可以直接用带页码的完整QueryKey来定位缓存并更新:
// 修改useMutation的入参,同时传入id和页码 const [deleteTodo, deletingMutation] = useMutation( ({ id, page }) => deleteTodo(id), { onSuccess: (_, { id, page }) => { // 用完整的QueryKey获取对应分页的缓存数据 const pageData = queryCache.getQueryData<any>(['todos', page]); if (pageData) { // 过滤掉被删除的todo,更新缓存 queryCache.setQueryData(['todos', page], { ...pageData, todos: pageData.todos.filter(todo => todo.id !== id) }); // 如果你的分页数据包含total计数,记得同步更新 // todos: pageData.todos.filter(...), // total: pageData.total - 1 } }, } ); // 调用删除方法时传入id和当前页码 deleteTodo({ id: todoId, page: currentPage });
2. 批量更新所有分页缓存(未知页码或统一更新)
如果不确定被删的todo在哪个分页,或者希望所有相关的分页缓存都同步更新,可以用queryCache.setQueriesData来匹配所有todos相关的查询键,批量修改缓存:
const [deleteTodo, deletingMutation] = useMutation( (id) => deleteTodo(id), { onSuccess: (_, deletedTodoId) => { // 匹配所有QueryKey第一个元素为'todos'的查询 queryCache.setQueriesData( (queryKey) => queryKey[0] === 'todos', (oldData) => { if (!oldData) return oldData; // 对每个分页的缓存数据进行过滤 return { ...oldData, todos: oldData.todos.filter(todo => todo.id !== deletedTodoId), // 同步更新总数(如果有) total: oldData.total - 1 }; } ); }, } );
3. 让所有分页查询失效,触发重新请求(适合数据可能有其他变动的场景)
如果不想手动修改缓存,或者担心后端数据还有其他同步变化,也可以直接让所有todos相关的查询失效,React Query会自动重新获取最新数据:
const [deleteTodo, deletingMutation] = useMutation( (id) => deleteTodo(id), { onSuccess: () => { // 使所有以'todos'为前缀的查询失效 queryCache.invalidateQueries('todos'); }, } );
注意:第三种方法会触发网络请求,如果你的场景对实时性要求高且不想有额外请求,优先选前两种方法。
内容的提问来源于stack exchange,提问作者Kamil P
相关产品推荐
相关产品推荐

