How to reset the state of a Redux store?

前端 未结 30 1873
陌清茗
陌清茗 2020-11-22 06:20

I am using Redux for state management.
How do I reset the store to its initial state?

For example, let’s say I have two user accounts (u1 and

相关标签:
30条回答
  • 2020-11-22 06:38

    Simply have your logout link clear session and refresh the page. No additional code needed for your store. Any time you want to completely reset the state a page refresh is a simple and easily repeatable way to handle it.

    0 讨论(0)
  • 2020-11-22 06:39

    for me what worked the best is to set the initialState instead of state:

      const reducer = createReducer(initialState,
      on(proofActions.cleanAdditionalInsuredState, (state, action) => ({
        ...initialState
      })),
    
    0 讨论(0)
  • 2020-11-22 06:40

    UPDATE NGRX4

    If you are migrating to NGRX 4, you may have noticed from the migration guide that the rootreducer method for combining your reducers has been replaced with ActionReducerMap method. At first, this new way of doing things might make resetting state a challenge. It is actually straight-forward, yet the way of doing this has changed.

    This solution is inspired by the meta-reducers API section of the NGRX4 Github docs.

    First, lets say your are combining your reducers like this using NGRX's new ActionReducerMap option:

    //index.reducer.ts
    export const reducers: ActionReducerMap<State> = {
        auth: fromAuth.reducer,
        layout: fromLayout.reducer,
        users: fromUsers.reducer,
        networks: fromNetworks.reducer,
        routingDisplay: fromRoutingDisplay.reducer,
        routing: fromRouting.reducer,
        routes: fromRoutes.reducer,
        routesFilter: fromRoutesFilter.reducer,
        params: fromParams.reducer
    }
    

    Now, lets say you want to reset state from within app.module `

    //app.module.ts
    import { IndexReducer } from './index.reducer';
    import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store';
    ...
    export function debug(reducer: ActionReducer<any>): ActionReducer<any> {
        return function(state, action) {
    
          switch (action.type) {
              case fromAuth.LOGOUT:
                console.log("logout action");
                state = undefined;
          }
    
          return reducer(state, action);
        }
      }
    
      export const metaReducers: MetaReducer<any>[] = [debug];
    
      @NgModule({
        imports: [
            ...
            StoreModule.forRoot(reducers, { metaReducers}),
            ...
        ]
    })
    
    export class AppModule { }
    

    `

    And that is basically one way to achieve the same affect with NGRX 4.

    0 讨论(0)
  • 2020-11-22 06:40

    One thing the solution in the accepted answer doesn't do is clear the cache for parameterized selectors. If you have a selector like this:

    export const selectCounter1 = (state: State) => state.counter1;
    export const selectCounter2 = (state: State) => state.counter2;
    export const selectTotal = createSelector(
      selectCounter1,
      selectCounter2,
      (counter1, counter2) => counter1 + counter2
    );
    

    Then you would have to release them on logout like this:

    selectTotal.release();
    

    Otherwise the memoized value for the last call of the selector and the values of the last parameters will still be in memory.

    Code samples are from the ngrx docs.

    0 讨论(0)
  • 2020-11-22 06:41

    My workaround when working with typescript, built on top of Dan's answer (redux typings make it impossible to pass undefined to reducer as first argument, so I cache initial root state in a constant):

    // store
    
    export const store: Store<IStoreState> = createStore(
      rootReducer,
      storeEnhacer,
    )
    
    export const initialRootState = {
      ...store.getState(),
    }
    
    // root reducer
    
    const appReducer = combineReducers<IStoreState>(reducers)
    
    export const rootReducer = (state: IStoreState, action: IAction<any>) => {
      if (action.type === "USER_LOGOUT") {
        return appReducer(initialRootState, action)
      }
    
      return appReducer(state, action)
    }
    
    
    // auth service
    
    class Auth {
      ...
    
      logout() {
        store.dispatch({type: "USER_LOGOUT"})
      }
    }
    
    0 讨论(0)
  • 2020-11-22 06:46

    A quick and easy option which worked for me was using redux-reset . Which was straightforward and also has some advanced options, for larger apps.

    Setup in create store

    import reduxReset from 'redux-reset'
    ...
    const enHanceCreateStore = compose(
    applyMiddleware(...),
    reduxReset()  // Will use 'RESET' as default action.type to trigger reset
    )(createStore)
    const store = enHanceCreateStore(reducers)
    

    Dispatch your 'reset' in your logout function

    store.dispatch({
    type: 'RESET'
    })
    

    Hope this helps

    0 讨论(0)
提交回复
热议问题