Reputation: 784
I have some resource, let's call it todos
.
I have list of it and user can delete on from list.
Before I implemented paginaiton that was looking like
const {data} = useQuery('todos', fetchTodos)
and in other place where I'm deleting it
const [deleteTodo, deletingMutation] = useMutation(
(id) => deleteTodo(id),
{
onSuccess: (data, deletedTodoId) => {
const { todos } = queryCache.getQueryData<any>('todos');
queryCache.setQueryData('todos', {
todos: todos.filter(todo=>todo.id !== deletedTodoId),
});
},
});
so in other place I'm just modyfing this data set called 'todos'
but After I implemented paginaiton things are more complicated because QueryKey isn't now just 'todos'
but it's ['todos', page]
so when I'm deleting todo and calling in onSuccess
this code queryCache.getQueryData<any>('todos');
, it returns me undefined
- because QueryKey contains additionally this page number.
How should I resolve it? Modyfing query data with paginated QueryKey.
Upvotes: 8
Views: 13211
Reputation: 113
The setQueriesData(...) seems to be intended for exactly that purpose:
setQueriesData is a synchronous function that can be used to immediately update cached data of multiple queries by using filter function or partially matching the query key.
So if you call setQueriesData with just the "todo" key I assume it will update all of them.
Thanks, Jesper
Upvotes: 0
Reputation: 76
I think I'm too late for you but i had the same problem and want to share my solution (although it's a little bit hacky)
I wrote a function which returns all the related cache keys
const getRelatedCacheKeys = (queryClient, targetKey) => {
return queryClient.getQueryCache().getAll()
.map(query => query.queryKey)
.filter(key => Array.isArray(key) ? key.includes(targetKey) : key === targetKey)
}
Then I call the setQueryData function for all related keys.
onSuccess: data => {
const keys = getRelatedCacheKeys(queryClient, 'key')
keys.forEach(key => {
queryClient.setQueryData(key, old => updateFn(old, data))
})
}
But the option to simply invalidate the cache seems tp be more practical
onSuccess: () => queryClient.invalidateQueries('key')
With this solution, all related keys also get invalidated
Upvotes: 4
Reputation: 797
To answer your question directly, you can provide a more specific key to getQueryData
:
queryCache.getQueryData<any>(['todos', page]);
Be aware that manually deleting in a pagination will create shift issues:
const paginatedTodos = [ [1, 2], [3, 4], [5, 6] ];
deleteTodoId(3);
// you would get [ [1, 2], [4], [5, 6] ]
// instead of [ [1, 2], [4, 5], [6] ]
You could try to fix the "hole" in the page, but to avoid any inconsistencies it may be better to simply invalidate all of the todos
queries to resynchronize with the actual data on your server.
Upvotes: 1