admin管理员组

文章数量:1289880

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 plicated 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.

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 plicated 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.

Share Improve this question asked Oct 30, 2020 at 12:00 Kamil PKamil P 7841 gold badge12 silver badges30 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

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

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.

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

本文标签: javascriptreactquerygetQueryData and setQueryData with paginationStack Overflow