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

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

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

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

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


当前回答

我发现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)
}

其他回答

为了将状态重置为初始状态,我编写了以下代码:

const appReducers = (state, action) =>
   combineReducers({ reducer1, reducer2, user })(
     action.type === "LOGOUT" ? undefined : state,
     action
);
 const reducer = (state = initialState, { type, payload }) => {

   switch (type) {
      case RESET_STORE: {
        state = initialState
      }
        break
   }

   return state
 }

你也可以触发一个动作,由所有或部分还原器处理,你想重置到初始存储。一个动作可以触发你整个状态的重置,或者只是适合你的一部分。我相信这是最简单、最可控的方法。

只需编辑声明约简的文件

import { combineReducers } from 'redux';

import gets from '../';

const rootReducer = (state, action) => {
  let asReset = action.type === 'RESET_STORE';

  const reducers = combineReducers({
    gets,
  });

  const transition = {
    true() {
      return reducers({}, action);
    },
    false() {
      return reducers(state, action);
    },
  };
  return transition[asReset] && transition[asReset]();
};

export default rootReducer;

使用Redux,如果应用了以下解决方案,它假设我已经在所有的reducers(例如{user: {name, email}})中设置了initialState。在许多组件中,我检查这些嵌套的属性,所以有了这个修复,我防止我的渲染方法在耦合属性条件上被破坏(例如if state.user。如果上面提到的解决方案,电子邮件将抛出一个错误用户是未定义的)。

const appReducer = combineReducers({
  tabs,
  user
})

const initialState = appReducer({}, {})

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

  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),但我不能容忍它,因为我喜欢元编程。