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