4

I have used redux persist with RTK query and redux toolkit. After clearing browser data manually from browser settings, it could not rehydrate RTK query reducer and showing

Uncaught TypeError: Cannot read properties of undefined (reading 'notesApi')
    at Object.extractRehydrationInfo (notesApi.js:18:1)
    at createApi.ts:234:1
    at memoized (defaultMemoize.js:123:1)
    at createApi.ts:260:1
    at memoized (defaultMemoize.js:123:1)
    at createReducer.ts:239:1
    at Array.filter (<anonymous>)
    at reducer (createReducer.ts:236:1)
    at reducer (createSlice.ts:325:1)
    at combination (redux.js:560:1).

Here is the screenshot of my problem.

Official Documentation says

  • RTK Query supports rehydration via the extractRehydrationInfo option on createApi. This function is passed every dispatched action, and where it returns a value other than undefined, that value is used to rehydrate the API state for fulfilled & errored queries.

But what about undefined value like in my case?

This is my store

const reducers = combineReducers({
  userReducer,
  [notesApi.reducerPath]: notesApi.reducer,
});

const persistConfig = {
  key: "root",
  storage,
};

const persistedReducer = persistReducer(
  persistConfig,
  reducers
);

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

export default store;

This is the notesApi

export const notesApi = createApi({
 reducerPath: "notesApi" ,
  baseQuery: fetchBaseQuery({
    baseUrl: "http://localhost:5000/api/notes/",
    prepareHeaders: (headers, { getState }) => {
      const token = getState().userReducer.userInfo.token;
      console.log(token);
      if (token) {
        headers.set("authorization", `Bearer ${token}`);
      }
      return headers;
    },
  }),
  extractRehydrationInfo(action, { reducerPath }) {
    if (action.type === REHYDRATE) {
        return action.payload[reducerPath]
    }
  },
  tagTypes: ["notes"],

  endpoints: (builder) => ({
    createNote: builder.mutation({
      query: (data) => ({
        url: `/create`,
        method: "POST",
        body: data,
      }),
      invalidatesTags: ["notes"],
    }),
    getSingleNote: builder.query({
      query: (id) => ({
        url: `/${id}`,
      }),
      providesTags: ["notes"],
    })
});
export const {  useGetSingleNoteQuery,
  useCreateNoteMutation,
} = notesApi;
Hasan
  • 41
  • 4

1 Answers1

2

I've run into this issue a few times and it seems to manifest when attempting to rehydrate the store when there isn't anything in localStorage to hydrate from.

The error is saying it can't read "notesApi" of undefined when running extractRehydrationInfo. "notesApi" is the API slice's reducerPath value. The action's payload is undefined.

extractRehydrationInfo(action, { reducerPath }) {
  if (action.type === REHYDRATE) {
    return action.payload[reducerPath]; // <-- action.payload undefined
  }
},

To resolve this issue I've simply used the Optional Chaining operator on the action payload.

Example:

extractRehydrationInfo(action, { reducerPath }) {
  if (action.type === REHYDRATE) {
    return action.payload?.[reducerPath];
  }
},
Drew Reese
  • 165,259
  • 14
  • 153
  • 181