Search code examples
reactjsreduxnext.jsredux-toolkit

How to use redux-persist with toolkit and next-redux-wrapper?


I'm having trouble with redux-toolkit, redux-persist, and next-redux-wrapper configuration. I've tried to make persist for redux state but it doesn't run redux actions which should save state to local storage.

My store.ts file.

import {
  Action,
  combineReducers,
  configureStore,
  ThunkAction,
  getDefaultMiddleware,
} from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { createWrapper } from 'next-redux-wrapper';
import taskReducer from './reducers/taskReducer';
import projectReducer from './reducers/projectReducer';
import workplaceReducer from './reducers/workplaceReducer';
import userReducer from './reducers/userReducer';
import trackTaskReducer from './reducers/trackTaskReducer';
import chatRoomReducer from './reducers/chatRoomReducer';
import messageReducer from './reducers/messageReducer';

const rootReducer = combineReducers({
  taskReducer,
  projectReducer,
  workplaceReducer,
  userReducer,
  trackTaskReducer,
  chatRoomReducer,
  messageReducer,
});

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

const persistedReducer = persistReducer(persistConfig, rootReducer);

const customizedMiddleware = getDefaultMiddleware({
  serializableCheck: false,
});

export const setupStore = () => {
  return configureStore({
    reducer: persistedReducer,
    middleware: customizedMiddleware,
  });
};

export type AppStore = ReturnType<typeof setupStore>;
export type AppState = ReturnType<AppStore['getState']>;
export type AppDispatch = AppStore['dispatch'];
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  AppState,
  unknown,
  Action
>;

export const wrapper = createWrapper<AppStore>(setupStore);

My app.tsx file

import React from 'react';
import AdapterDateFns from '@mui/lab/AdapterDateFns';
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';

import { useRouter } from 'next/router';
import type { AppProps } from 'next/app';
import { setupStore, wrapper } from '../store/store';

export default wrapper.withRedux(function MyApp({
  Component,
  pageProps,
}: AppProps) {
  const persistor = persistStore(setupStore());
  return (
      <PersistGate persistor={persistor} loading={<div>Loading</div>}>
        <Component {...pageProps} />
      </PersistGate>
  );
});

It's saving the initial state to local storage but it isn't saving future changes to the state. What am I doing wrong?


Solution

  • So i found solution for me:

    import {
      Action,
      combineReducers,
      configureStore,
      ThunkAction,
      getDefaultMiddleware,
    } from '@reduxjs/toolkit';
    import { persistReducer, persistStore } from 'redux-persist';
    import storage from 'redux-persist/lib/storage';
    
    const rootReducer = combineReducers({
      // your reducers
    });
    
    const persistConfig = {
      key: 'root',
      storage,
    };
    
    const persistedReducer = persistReducer(persistConfig, rootReducer);
    
    const customizedMiddleware = getDefaultMiddleware({
      serializableCheck: false,
    });
    
    export const setupStore = () => {
      return configureStore({
        reducer: persistedReducer,
        middleware: customizedMiddleware,
      });
    };
    
    export const persistedStore = () => persistStore(setupStore());
    
    export type AppStore = ReturnType<typeof setupStore>;
    export type AppState = ReturnType<AppStore['getState']>;
    export type AppDispatch = AppStore['dispatch'];
    export type AppThunk<ReturnType = void> = ThunkAction<
      ReturnType,
      AppState,
      unknown,
      Action
    >;
    
    export const store = setupStore();
    

    Warning: your reducers must have this extra reducer like that:

    extraReducers: {
    [HYDRATE]: (state, action) => {
      return {
        ...state,
        ...action.payload.chatRoom,
      };
    },
    

    Also i don't know if it will work with SSR because i don't need that feature in my case