How to reset the state of a Redux store?

2019-01-01 01: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 u2).
Imagine the following sequence of events:

  1. User u1 logs into the app and does something, so we cache some data in the store.

  2. User u1 logs out.

  3. User u2 logs into the app without refreshing the browser.

At this point, the cached data will be associated with u1, and I would like to clean it up.

How can I reset the Redux store to its initial state when the first user logs out?

24条回答
泛滥B
2楼-- · 2019-01-01 01:52

With Redux if have applied the following solution, which assumes I have set an initialState in all my reducers (e.g. { user: { name, email }}). In many components I check on these nested properties, so with this fix I prevent my renders methods are broken on coupled property conditions (e.g. if state.user.email, which will throw an error user is undefined if upper mentioned solutions).

const appReducer = combineReducers({
  tabs,
  user
})

const initialState = appReducer({}, {})

const rootReducer = (state, action) => {
  if (action.type === 'LOG_OUT') {
    state = initialState
  }

  return appReducer(state, action)
}
查看更多
不流泪的眼
3楼-- · 2019-01-01 01:54

Define an action:

const RESET_ACTION = {
  type: "RESET"
}

Then in each of your reducers assuming you are using switch or if-else for handling multiple actions through each reducer. I am going to take the case for a switch.

const INITIAL_STATE = {
  loggedIn: true
}

const randomReducer = (state=INITIAL_STATE, action) {
  switch(action.type) {
    case 'SOME_ACTION_TYPE':

       //do something with it

    case "RESET":

      return INITIAL_STATE; //Always return the initial state

   default: 
      return state; 
  }
}

This way whenever you call RESET action, you reducer will update the store with default state.

Now, for logout you can handle the like below:

const logoutHandler = () => {
    store.dispatch(RESET_ACTION)
    // Also the custom logic like for the rest of the logout handler
}

Every time a userlogs in, without a browser refresh. Store will always be at default.

store.dispatch(RESET_ACTION) just elaborates the idea. You will most likely have an action creator for the purpose. A much better way will be that you have a LOGOUT_ACTION.

Once you dispatch this LOGOUT_ACTION. A custom middleware can then intercept this action, either with Redux-Saga or Redux-Thunk. Both ways however, you can dispatch another action 'RESET'. This way store logout and reset will happen synchronously and your store will ready for another user login.

查看更多
公子世无双
4楼-- · 2019-01-01 01:55

Just a simplified answer to the best answer:

const rootReducer = combineReducers({
    auth: authReducer,
    ...formReducers,
    routing
});


export default (state, action) => (
    action.type === 'USER_LOGOUT'
        ? rootReducer(undefined, action)
        : rootReducer(state, action)
)
查看更多
姐姐魅力值爆表
5楼-- · 2019-01-01 01:55

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.

查看更多
流年柔荑漫光年
6楼-- · 2019-01-01 01:57

I'd like to point out that the accepted comment by Dan Abramov is correct except we experienced a strange issue when using the react-router-redux package along with this approach. Our fix was to not set state to undefined but rather still use the current routing reducer. So I would suggest implementing the solution below if you are using this package

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    const { routing } = state
    state = { routing } 
  }
  return appReducer(state, action)
}
查看更多
宁负流年不负卿
7楼-- · 2019-01-01 01:58

Combining the approaches of Dan, Ryan and Rob, to account for keeping the router state and initializing everything else in the state tree, I ended up with this:

const rootReducer = (state, action) => appReducer(action.type === LOGOUT ? {
    ...appReducer({}, {}),
    router: state && state.router || {}
  } : state, action);
查看更多
登录 后发表回答