我正在使用Redux进行状态管理。 如何将存储重置为初始状态?

例如,假设我有两个用户帐户(u1和u2)。 想象下面的一系列事件:

用户u1登录到应用程序并做了一些事情,所以我们在存储中缓存一些数据。 用户u1退出。 用户u2无需刷新浏览器即可登录应用。

此时,缓存的数据将与u1关联,我想清理它。

当第一个用户注销时,如何将Redux存储重置为初始状态?


当前回答

对我来说,一个快速而简单的选择是使用还原复位。这是简单的,也有一些高级选项,为较大的应用程序。

在创建存储区中设置

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)

在注销函数中调度您的“重置”

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

其他回答

只需将注销链接清除会话并刷新页面。您的商店不需要额外的代码。当您想要完全重置状态时,页面刷新是一种简单且易于重复的处理方法。

另一种选择是:

store.dispatch({type: '@@redux/INIT'})

'@@redux/INIT'是redux自动调度的动作类型,当你创建存储时,所以假设你的reducers都有一个默认值,这将被那些捕获,并开始你的状态新鲜。不过,它可能被认为是redux的私有实现细节,所以买家要小心……

我在使用typescript时的解决方案,建立在Dan Abramov的答案之上(redux类型使得不可能将undefined作为第一个参数传递给reducer,所以我将初始根状态缓存在一个常量中):

// 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"})
  }
}

使用Redux Toolkit和/或Typescript:

const appReducer = combineReducers({
  /* your app’s top-level reducers */
});

const rootReducer = (
  state: ReturnType<typeof appReducer>,
  action: AnyAction
) => {
/* if you are using RTK, you can import your action and use it's type property instead of the literal definition of the action  */
  if (action.type === logout.type) {
    return appReducer(undefined, { type: undefined });
  }

  return appReducer(state, action);
};

我发现Dan Abramov的回答很适合我,但它触发了ESLint no-param-reassign错误- https://eslint.org/docs/rules/no-param-reassign

下面是我如何处理它,确保创建一个状态的副本(这是,在我的理解,Reduxy的事情要做…):

import { combineReducers } from "redux"
import { routerReducer } from "react-router-redux"
import ws from "reducers/ws"
import session from "reducers/session"
import app from "reducers/app"

const appReducer = combineReducers({
    "routing": routerReducer,
    ws,
    session,
    app
})

export default (state, action) => {
    const stateCopy = action.type === "LOGOUT" ? undefined : { ...state }
    return appReducer(stateCopy, action)
}

但是也许创建一个状态的副本,然后把它传递给另一个减速器函数,它会创建一个状态的副本,这有点过于复杂了?这篇文章读起来不太好,但更切题:

export default (state, action) => {
    return appReducer(action.type === "LOGOUT" ? undefined : state, action)
}