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

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

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

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

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


当前回答

Dan Abramov的答案是正确的,除了我们在使用react-router-redux包时遇到了一个奇怪的问题。

我们的解决方案是不将状态设置为undefined,而是仍然使用当前的路由减速器。因此,如果您正在使用这个包,我建议实现下面的解决方案

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    const { routing } = state
    state = { routing } 
  }
  return appReducer(state, action)
}

其他回答

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

在创建存储区中设置

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'
})

使用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);
};

如果你正在使用还原动作,这里有一个快速的解决方案,使用HOF(高阶函数)为handleActions。

import { handleActions } from 'redux-actions';

export function handleActionsEx(reducer, initialState) {
  const enhancedReducer = {
    ...reducer,
    RESET: () => initialState
  };
  return handleActions(enhancedReducer, initialState);
}

然后使用handleActionsEx代替原来的handleActions来处理reducers。

Dan的回答给出了关于这个问题的一个很好的想法,但它对我来说并不是很有效,因为我使用的是还原坚持。 当使用redux-persist时,简单地传递未定义的状态不会触发持久化行为,所以我知道我必须手动从存储中删除项目(在我的情况下,React Native,因此AsyncStorage)。

await AsyncStorage.removeItem('persist:root');

or

await persistor.flush(); // or await persistor.purge();

对我也没用——他们只是对我大喊大叫。(例如,抱怨“意外的键_persist…”)

然后我突然思考,我想要的只是让每个减速机在遇到RESET动作类型时回到自己的初始状态。这样,持久化就被自然地处理了。显然没有上面的实用函数(handleActionsEx),我的代码不会看起来很干(虽然它只是一个一行程序,即RESET: () => initialState),但我不能容忍它,因为我喜欢元编程。

除了Dan Abramov的回答之外,我们是否应该明确地将action设置为action = {type: '@@INIT'}以及state = undefined。采用上述动作方式,各减速器均返回初始状态。

你可以通过将此代码添加到动作文件中来清空减速器的数据,

首先导入所有类型:

import * as types from './types';

将此代码添加到注销操作

for(let key of Object.values(types)) {
        dispatch({ type: key, payload: [] });
    }