reduxjs / redux-toolkit

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

invalidateTags only seems to work with a setTimeout #4706

Open wmonecke-oss opened 2 days ago

wmonecke-oss commented 2 days ago

Hey there!

When I get a web socket update I want to refetch data.

This setup is working (notice setTimeout):


  useEffect(() => {
    if (!enabled) {
      return;
    }

    prettyLog('FETCHING WEATHER');

    dispatch(Api.util.invalidateTags([ApiCacheTags.FetchWeather]));

    // wait for cache invalidation
    setTimeout(() => {
      dispatch(syncWeatherForCurrentLocation());
    }, 1000);
  }, [
    dispatch,
    enabled,
    realTimeChanges.update,
  ]);

This is NOT working:

  useEffect(() => {
    if (!enabled) {
      return;
    }

    prettyLog('FETCHING ALERTS FOR LOCATIONS');

    dispatch(Api.util.invalidateTags([ApiCacheTags.FetchWeather]));

    dispatch(syncWeatherForCurrentLocation());
  }, [
    dispatch,
    enabled,
    realTimeChanges.update,
  ]);

I thought invalidateTags was a synchronous call. How would I await it here? Or what else am I missing?

markerikson commented 2 days ago

What are you trying to accomplish? Are you trying to wait for all the invalidated cache entry requests to complete?

invalidateTags itself is a synchronous action that tells the RTKQ middleware to start the fetching process. It doesn't have any knowledge of what requests got kicked off or how they completed.

If you need to know when the requests are done, you'd probably need:

wmonecke-oss commented 1 day ago

@markerikson ah i see thanks!

this is what i was trying to accomplish:

  1. invalidate cache
  2. next time i call that endpoint it wont return cached data

so here is my problem, (see first message):

inside dispatch(syncWeatherForCurrentLocation());

i have an api call that returns cached data:

   // fetch weather for current position
    const promiseromise = thunkApi
      .dispatch(
        Weather.endpoints.fetchWeatherByCoordinate.initiate(
          currentLocation.position.coordinate,
        ),
      )
      .unwrap();

even when before that i called dispatch(Api.util.invalidateTags([ApiCacheTags.FetchWeather]));

After the invalidateTags call, I expected all cached data would have been invalidated and the next API call would have been fresh data.

EDIT:

I followed your recommendation but it still did not work:

const fetchAlerts = async () => {
      prettyLog('Fetching alerts for locations');

      dispatch(Weather.util.invalidateTags([ApiCacheTags.FetchWeather]));

      // only works w this delay, if i remove this delay then the call in 
      // syncWeatherForCurrentLocation returns cached data
      await new Promise(resolve => setTimeout(resolve, 1000)); 

      // this return empty array always, with or without the delay above
      const queries = await Promise.all(
        dispatch(Weather.util.getRunningQueriesThunk()),
      );

      prettyLog('Cache invalidation complete', { queries });

        dispatch(syncWeatherForCurrentLocation()),
    };
markerikson commented 1 day ago

Invalidation kicks off a new request, but it doesn't remove the existing cache entry.