reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.74k stars 1.18k forks source link

[RTKQuery] How to clear the cache of a query #4504

Open fabripetrelli opened 4 months ago

fabripetrelli commented 4 months ago

I'm currently in a situation where I'm questioning the best way to handle this situation with RTKQuery:

I have a table that displays a set of data. In this table, you have the possibility to select a single item that lets you view further details on a map. The application also has the functionality of creating new entries in this table. So, logically, when you are creating a new entry, you don't want to see the details of the previously selected entry on the map. Currently, I achieve this with a boolean in a piece of redux state that I'm also using in other components; let's call it isCreateMode.

Here is the code:

Map.tsx:

<Map>
  {!isCreateMode && <ComponentThatShowsTheSelectedEntryDetails />}
</Map>

The problem with this code is that whenever I decide to cancel the addition of a new entry to the table or proceed with the creation of it, I will set isCreateMode to false, and then the previously selected data shows the details on the map.

How can I remove the data from the query when I set isCreateMode to true, so that when it returns to false, the map doesn't show the previously selected details?

I've tried to use api.util.updateQueryData('tagToBeInvalidated', undefined, () => undefined) but it didn't work. I've also tried to use api.util.invalidateTags, but this obviously triggers a refetch with the latest argument, so it's not good for my situation.

I think that duplicating the state in a useState to have easier control isn't the best solution, so I'm trying to avoid it.

Also posted this question on StackOverflow

fabripetrelli commented 4 months ago

After some research, I managed to resolve the issue by using a mutation instead of a query. I knew that with a mutation comes a reset state function, but I didn't want to use it since I thought that using a mutation for things that aren't create, update, or delete APIs was not the right thing to do. However, after searching, I've discovered that it is totally fine to do that for handling side-effect such in my case.

I wonder if there are also other ways to handle this.

LandroNoInc commented 3 months ago

i have run into the same issue. Especially for lazy queries where querying is done programmatically, there should be a way to clear the returned result object to reset state to prepare for a subsequent query.

For example I have the following

const TestComponent = ({ selectedItem }) => {
  const [triggerDownload, result] = useLazyQuery();

  const handleClick = () => {
    triggerDownload.then((res) => download(res));
  }

  return (
    <ButtonThatHandlesState result={result} item={selectedItem} onClick={handleClick} />
  )
}

If my selectedItem changes for this component, the now irrelevant result remains. There should be a cleaner way to reset the result object once it's determined to be unnecessary.

evgeniyworkbel commented 2 months ago

the reset method for lazy query hooks is sorely lacking...

phryneas commented 2 months ago

@evgeniyworkbel It resets the hook, to "not subscribed to a cache entry", not the cache. Never stated anything else anywhere.