skip to Main Content

I’m using @reduxjs/toolkit/query to fetch data from my API in a React application. I’m using the useQuery hook to perform the query, but the data is not being cached as expected.

Here is my code:

// Define the API using createApi
export const defaultApi = createApi({
  reducerPath: 'defaultApi',
  baseQuery: fetchBaseQuery({
    baseUrl: process.env.REACT_APP_API_URL,
    prepareHeaders: (headers, { getState }) => {
      const {
        auth: { accessToken }
      } = getState() as any
      if (accessToken) {
        headers.set('Authorization', `Bearer ${accessToken}`)
      }
      return headers
    }
  }),
  endpoints: (builder) => ({
    products: builder.query<Product[], void>({
      query: () => {
        return {
          url: `/api/user/products`,
          providesTags: ['products'],
        }
      }
    })
  }),
})

My store:

import { AnyAction, configureStore, ThunkDispatch } from "@reduxjs/toolkit";
import { defaultApi } from "apis/default";
import { useDispatch } from "react-redux";
import {
  createMigrate,
  FLUSH,
  PAUSE,
  PERSIST, PersistedState, persistReducer,
  persistStore,
  PURGE,
  REGISTER,
  REHYDRATE
} from "redux-persist";
import storage from "redux-persist/lib/storage";
import rootReducer from "./rootReducer";

const migrations = {
  0: (state: PersistedState) => {
    return {
      _persist: {
        rehydrated: true,
        version: state?._persist?.version ?? 0,
      },
    };
  },
};

const persistConfig = {
  key: "primary",
  version: 15,
  storage,
  migrate: createMigrate(migrations, { debug: false }),
  whitelist: [
    "auth",
  ],
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) => [
    ...getDefaultMiddleware({
      serializableCheck: {
        ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
      immutableCheck: false,
    }),
    defaultApi.middleware,
  ],
});

export default store;



type TypedDispatch<T> = ThunkDispatch<T, any, AnyAction>;

export type RootState = ReturnType<typeof store.getState>;
export const useAppDispatch = () => useDispatch<TypedDispatch<RootState>>();

const persistor = persistStore(store);

export { persistor };

My component:

// Use the query in a component
const MyComponent = () => {
  const {
    data: products,isLoading,isSuccess,isFetching
  } = useProductsQuery();
  
  useEffect(() => {
    console.log("πŸš€ ~ file: index.tsx:22 ~ isLoading:", isLoading)
    console.log("πŸš€ ~ file: index.tsx:22 ~ isSuccess:", isSuccess)
    console.log("πŸš€ ~ file: index.tsx:22 ~ isFetching:", isFetching)
  },[isLoading,isSuccess,isFetching])
  // ...
}

I know the request if being made from watching Network tab but also every time I refresh the page, console return:

πŸš€isLoading: true

πŸš€ isSuccess: false

πŸš€ isFetching: true

πŸš€ isLoading: false

πŸš€ isSuccess: true

πŸš€ isFetching: false

Already tried setting providesTags to [] and cacheTime: 3600000 // cache for 1 hour

I expect to have endpoint called only once I load page for the first time.

2

Answers


  1. RTK Query, like Redux itself, is an in-memory-cache. It keeps data around while you navigate around in your application (assuming you navigate correctly with your router library).

    When you press F5, you kill the whole app and start it again. In that case, all memory has been erased, and data needs fetching again.

    Login or Signup to reply.
  2. The library you are using provides in-memory caching, which means that the cache is alive as long as your page is alive. Cache is cleared and network fetch is initiated every time you refresh the page.

    If you would like to persist network-fetched data across page refresh/reloads, you can try using browser storage options like localstorage, sessionstorage, indexeddb etc.

    Here are some links that might help you:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search