Search code examples
reduxreact-reduxstate-managementreact-boilerplate

reset redux store on logout when using react-injectors


I have the same problem as addressed in the following question. but with a different library. How to reset the state of a Redux store?

I am using redux-injectors from react-boilerplate and am using the enhancers provided from the library. I need to clear all the redux state on logout, but since my logout is on a separate global slice it can only affect the global slice and not other redux states. How do I clear all other states calling an action from global state?

Here's how I combine reducers:

import { combineReducers } from '@reduxjs/toolkit';

export function createReducer(injectedReducers = {}) {
  if (Object.keys(injectedReducers).length === 0) {
    return state => state;
  }
  return combineReducers({
    ...injectedReducers
  });
}

my globalReducer:

import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  loading: false
};

const globalSlice = createSlice({
  name: 'global',
  initialState,
  reducers: {
    logout(state) {
      return state;
    }
  }
});

export const { actions, reducer, name: sliceKey } = globalSlice;

my store/index.js

import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import { createInjectorsEnhancer, forceReducerReload } from 'redux-injectors';
import createSagaMiddleware from 'redux-saga';
import { createReducer } from './reducers';

function configureAppStore() {
  const reduxSagaMonitorOptions = {
    onError: (error, { sagaStack }) => {
      // console.log(error, sagaStack);
    }
  };
  const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
  const { run: runSaga } = sagaMiddleware;

  // Create the store with saga middleware
  const middlewares = [sagaMiddleware];

  const enhancers = [
    createInjectorsEnhancer({
      createReducer,
      runSaga
    })
  ];

  const store = configureStore({
    reducer: createReducer(),
    middleware: [
      ...getDefaultMiddleware({
        serializableCheck: {
          ignoredActionPaths: ['payload.history']
        },
        immutableCheck: false
      }),
      ...middlewares
    ],
    devTools:
      process.env.NODE_ENV !== 'production'
      || process.env.PUBLIC_URL.length > 0,
    enhancers
  });

  // Make reducers hot reloadable, see http://mxs.is/googmo
  if (module.hot) {
    module.hot.accept('./reducers', () => {
      forceReducerReload(store);
    });
  }

  return store;
}

export const store = configureAppStore();

Solution

  • One solution could be to -

    1. Define an "injected saga" for each of the "injected-reducer" which is side-effected by the "logout" action.
    2. In so defined "injected-saga", define clean-up actions particular to that injected reducer, while observing for the "logout" action.
    3. So, in theory, when "logout" action is dispatched all the injected saga defined like above will run the clean-up actions resulting in logout equivalent slice in individual reducers.

    Try this and this should sort that out.

    :: Updated ::

    A little difference to avoid creating saga for all the other relevant component/slices.

    Working prototype - https://stackblitz.com/edit/inject-reducer?devtoolsheight=33&file=src/App.js