redux-persist icon indicating copy to clipboard operation
redux-persist copied to clipboard

Redux persist is not working when redux dev tool is disabled.

Open priosshrsth opened this issue 4 years ago • 4 comments
trafficstars

In my app, redux persist was not working in production. But, everything was working fine on development environment. Turns out it only works when redux dev tool is enabled, which was disabled in production mode. Is it supposed to be like this? I am using these packages in my next.js app:

"@reduxjs/toolkit": "^1.5.0",
"react-redux": "^7.2.2",
"redux-persist": "^6.0.0",
"next": "10.0.3",

Here is my code:

import { combineReducers, configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import reducerRegistry from 'redux/reduxRegistry';
import { useDispatch } from 'react-redux';
import login from 'features/login/login.slice';
import notification from 'features/notification/notification.slice';
import { FLUSH, PAUSE, PERSIST, persistReducer, persistStore, PURGE, REGISTER, REHYDRATE } from 'redux-persist';
import createWebStorage from 'redux-persist/lib/storage/createWebStorage';

const createNoopStorage = () => {
  return {
    getItem(_key) {
      return Promise.resolve(null);
    },
    setItem(_key, value) {
      return Promise.resolve(value);
    },
    removeItem(_key) {
      return Promise.resolve();
    },
  };
};

const storage = typeof window !== 'undefined' ? createWebStorage('local') : createNoopStorage();

const isProduction = process.env.NODE_ENV === 'production';

const combine = (asyncReducers = {}) => {
  return combineReducers({
    auth: login,
    notification,
    ...asyncReducers,
  });
};

const persistConfig = {
  key: 'root',
  storage,
  whitelist: ['auth', 'register'],
};

const persistedReducer = persistReducer(persistConfig, combine());

const getMiddlewares = (getDefaultMiddleware) => {
  const defaultMiddlewares = getDefaultMiddleware({
    serializableCheck: {
      ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
    },
  });
  if (isProduction) {
    return defaultMiddlewares;
    // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require
    // const { logger } = require('./_fake/logger');
    // return defaultMiddlewares.concat(logger);
  }
  // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require
  const { logger } = require('redux-logger');
  return defaultMiddlewares.concat(logger);
};

export const store = configureStore({
  reducer: persistedReducer,
  middleware: getMiddlewares,
  devTools: false, // It works fine if I set this to true
});

reducerRegistry.setChangeListener((reducers) => {
  store.replaceReducer(persistReducer(persistConfig, combine(reducers)));
});

export const persistor = persistStore(store);

export type RootState = ReturnType<typeof store.getState>;
// @ts-ignore
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>;

export type AppDispatch = typeof store.dispatch;
export const useAppDispatch = () => useDispatch<AppDispatch>();

export const dispatcher = store.dispatch as ReturnType<typeof useAppDispatch>;

priosshrsth avatar Mar 24 '21 09:03 priosshrsth

Yeah, I found this issue too.

After review, I realized that I am using redux-injectors to combine the reducers dynamically. Thus I have to set the option: manualPersist: true and manually dispatch the persist event later.

mutoo avatar Apr 25 '21 12:04 mutoo

@mutoo do you call persistor.persist or do you use store.dispatch to call the persist method? Please share your solution for this

smac89 avatar Dec 18 '21 16:12 smac89

@mutoo do you call persistor.persist or do you use store.dispatch to call the persist method? Please share your solution for this

hi @smac89 here is the code related to my issue

the persistor with manualPersist disabled: https://github.com/mutoo/critterpedia-plus/blob/d0be98768a6bc87ff01e006cceaa57092c9730ab/app/configureStore.js#L65

export const persistor = persistStore(store, { manualPersist: false });

the component that injects persistReducer and manually dispatches persist with persistor: https://github.com/mutoo/critterpedia-plus/blob/d0be98768a6bc87ff01e006cceaa57092c9730ab/app/pages/Critterpedia/index.js#L46

  useInjectReducer({ key, reducer });
  useEffect(() => {
    persistor.persist();
  }, []);

I hope this will help you.

mutoo avatar Dec 19 '21 07:12 mutoo

Hi there! Same issue here. Any solutions? Not using redux-injectors

natoszme avatar Oct 14 '22 18:10 natoszme