【问题标题】:Redux reducer - on state changeRedux reducer - 状态变化
【发布时间】:2023-03-23 17:45:01
【问题描述】:

我想将特定 reducer 的当前状态保存到会话存储中,而不是在每个操作上显式调用它。

const { handleActions } = require("redux-actions");

// How do i make this logic run on any state change without adding it to every action?
const onStateChange = (state) => sessionStorage.save(keys.myReducer, state);

const myReducer = handleActions
({
     [Actions.action1]: (state, action) => (
         update(state, {
             prop1: {$set: action.payload},
         })
     ),
     [Actions.action2]: (state, action) => (
         update(state, {
             prop2: {$set: action.payload},
         })
     )
 },
 //****************INITIAL STATE***********************
 {
     prop1: [],
     prop2: []
 }
);

有没有办法捕捉特定 reducer 的状态变化事件?

我知道store.subscribe,但这是针对整个商店的,我说的是监听特定的减速器变化

谢谢

【问题讨论】:

  • 你试过像redux-localstorageredux-persist这样的库吗?还是您正在解决这些库未解决的利基用例?
  • @excalliburbd - 保持状态不是我想要在状态更改时运行的唯一逻辑,所以不幸的是这并不能解决问题

标签: javascript reactjs redux state


【解决方案1】:

很遗憾,您无法查看商店的特定部分,因为您的商店实际上是唯一的减速器(combineReducers 返回一个大减速器)。也就是说,您可以通过进行状态部分比较来手动检查减速器是否已更改。

let previousMyReducer = store.getState().myReducer;
store.subscribe(() => {
  const { myReducer } = store.getState();
  if (previousMyReducer !== myReducer) {
    // store myReducer to sessionStorage here
    previousMyReducer = myReducer;
  }
})

【讨论】:

  • 您确定这样的参考比较有效吗?如果任何值发生变化,reducers 的参考是否会发生变化(并且只会发生变化)?
  • 是的,这是reducer不变性的主要优点,当reducer不拦截动作时,返回相同的状态引用
【解决方案2】:

您可以使用redux-saga 来侦听特定操作并在它们被触发时保持存储(并执行您的其他逻辑)。这似乎很适合您的需求。

它并不完全与特定的商店更改相关,而是与一组操作相关。但是,我认为这种模型(监听动作,而不是状态变化)更适合 redux 设计。

好处是您不必更改传奇之外的任何代码。我用这个来自动保存表单数据,效果很好。

这是一个设置 saga 以坚持几个 redux-form 操作的示例;请注意,它不仅限于坚持——您可以在传奇期间做任何您想做的事情。

function* autosaveSaga(apiClient) {
  yield throttle(500,
  reduxFormActionTypes.CHANGE,
    saveFormValues,
    apiClient);

  yield takeLatest(
    reduxFormActionTypes.ARRAY_PUSH,
    saveFormValues,
    apiClient);

  yield takeLatest(
    reduxFormActionTypes.ARRAY_POP,
    saveFormValues,
    apiClient);
 }

如果您想监听所有动作类型,或自定义过滤哪些动作触发您的持久性代码,您可以将模式或匹配函数传递给 takeLatest:

   yield takeLatest(
    '*',
    saveFormValues,
    apiClient);

有关您可以传递给taketakeLatest 等的更多信息,请访问in the docs for take

【讨论】:

  • 谢谢,但这正是我想要避免的......(在每个动作上写相同的行)
  • 我的例子不是最优的。更新以说明您可以使用模式或匹配所有操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
  • 2018-08-04
  • 1970-01-01
相关资源
最近更新 更多