【问题标题】:Unexpected redux state flushing意外的 redux 状态刷新
【发布时间】:2020-06-26 05:04:17
【问题描述】:

我有一个 reducer 和一个初始的 redux 状态。

const initialState = {
   arrayValue: ['1', '2']
};

export const reducer(state = initialState, action) {
   switch (action.type) {
      case 'ARRAY_CHANGE': {
      return {
           ...state,
           arrayValue: [...action.payload]
         }
      }
      default:
         return state;
   }
}

reducer 按预期工作。奇怪的是,当我转到另一个页面然后返回上一个页面时,arrayValue 变为空。我有很多其他的减速器,它们工作得非常好。

我通过调试器检查了带有'ARRAY_CHANGE' 类型的dispatch 调用,我没有发现任何可疑之处。看起来arrayValue 只是无缘无故地变空了。有人有什么想法吗?

编辑: 我通过 Redux 开发工具检查了状态。当我转到另一个页面时,arrayValues 变成了一个空数组,尽管没有使用 'ARRAY_CHANGE' 类型的 dispatch 调用。也许 react-router 存在一些问题。

这就是将值传递给组件的方式。

export default connect(
  state => (
    {arrayValue: state.app.reducer.arrayValue}
  ),
  dispatch => ({
    onChangeArrayValues: arrayValue => 
        dispatch({type: 'ARRAY_CHANGE', payload: arrayValue})
  })
)(MyComponent)

EDIT2: 好的,我已经再次调试了代码,这是我发现的。 我有一个组合减速器。

const appReducers = combineReducer({
  ui: uiReducer,
  reducer
});


...
const initialState = {
   spinner: false,
}

function uiReducer(state = initialState, action) {
   switch(action.type) {
      case SPINNER_SHOW: {
         return {...state, spinner: true};
      }
      case SPINNER_HIDE: {
         return {...state, spinner: false};
      }
      default:
         return state;
   }
}

这两个减速器是分开的。但这是 SPINNER_SHOW 事件发生的情况。对象结构与我描述的有点不同。不要在意这个。

selectedNodeVerifications 更改 ARRAY_VALUE

SPINNER_SHOW 事件

这两个事件被放置在不同的 reducer 中。我不知道SPINNER_SHOW 会如何影响selectedNodeVerifications

【问题讨论】:

  • 页面是如何渲染的?它是否在任何生命周期函数中调度 ARRAY_CHANGE 操作?您是否正在通过 redux 开发工具检查您的 redux 状态?或记录它?你如何验证它不是你所期望的?它是一个空对象、空数组还是别的什么?是否还有其他东西可以发送带有空负载的 ARRAY_CHANGE 操作?
  • 我对问题添加了一些解释
  • 我看到 redux 状态神秘变化的另一次是当对状态值的引用在其他地方发生突变时。能否也提供有问题的组件代码?
  • 我补充了一些解释

标签: reactjs redux state reducers state-management


【解决方案1】:

我找到了某种解决方案。

const initialState = {
   arrayValue: ['1', '2'].join(',')
};

export const reducer(state = initialState, action) {
   switch (action.type) {
      case 'ARRAY_CHANGE': {
      return {
           ...state,
           arrayValue: action.payload.join(',')
         }
      }
      default:
         return state;
   }
}

...

export default connect(
  state => (
    {arrayValue: state.app.reducer.arrayValue.split(',')}
  ),
  dispatch => ({
    onChangeArrayValues: arrayValue => 
        dispatch({type: 'ARRAY_CHANGE', payload: arrayValue})
  })
)(MyComponent)

这是一种肮脏的方法,但它有效。我仍然不明白为什么 Redux 对数组值的行为如此奇怪。

【讨论】:

  • 我想你找到解决方法没关系,但是如果这是拉取请求中的生产代码,我不会让它被合并。我仍然怀疑您的 UI 代码中的某些内容正在改变您的状态参考。继续追踪……MyComponent(或使用它的任何组件)对来自connect HOC 的arrayValue 做了什么?
  • 我找到了问题的根源。这是由我们在项目中使用的组件库引起的。它提供了一个自定义的CheckboxGroup,它接受一个值数组。问题是onChange 事件应该返回一个新数组。但相反,它会在原地对其进行变异。当我将数组的副本作为属性 ([...props.values]) 传递时,一切都开始按预期工作。
  • 是的,太棒了!状态突变有时可能是真正需要调试的。
猜你喜欢
  • 2018-03-22
  • 2019-01-20
  • 2018-05-29
  • 1970-01-01
  • 2019-10-02
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
相关资源
最近更新 更多