通过引用传递赋值mutate redux state

时间:2017-08-26 23:40:47

标签: javascript redux redux-thunk

我有一个带有项目菜单的应用程序,在某些时候用户可以编辑项目的值。当用户这样做时,我在单独的状态分支中创建项目的副本,而不是更改原始菜单项。所以我的减速机看起来像这样:

const menuReducer = (state = [], action) => {
  switch (action.type) {
    case ADD_ITEM:
      return [...state, {id: action.itemId, propA: action.itemPropA, propB: action.itemPropB}]
  }
}

const editingMenuItem = (state = {}, action) => {
  switch (action.type) {
    case SET_EDIT_ITEM:
      return {id: action.id, propA: action.itemPropA, propB: action.itemPropB}
    case EDIT_ITEM:
      return {id: state.id, propA: action.itemPropA, propB: action.itemPropB}
  }
}

有人选择他们想要编辑一个项目,这会导致dispatchEditItem thunk触发并在状态树中创建一个副本:

const dispatchEditItemThunk = itemId => (dispatch, getState) => {
  const item = _.find(getState().menu, ['id', itemId]);
  dispatch(setEditItem(item.id, item.propA, item.propB))
}

然后当有人想要编辑道具时,会发送editingThunk

const editingThunk = (itemId, propName) => (dispatch, getState) => {
  let activeItem = getState().editingMenuItem;
  // someValue is generated here
  activeItem[propName] = someValue
  dispatch(editItem(activeItem.propA, activeItem.propB))
}

问题在于,当activeItem[propName] = someValue发生时,此会更改menuReducer数组中包含的项的值。我假设因为所有内容都是通过引用传递的,并且所有引用都返回到menuReducer中的原始值。但是,这并不是我希望这种方式发挥作用的方式。我的假设是调用getState将返回该州的深层副本,并且不允许这些意外突变。

这是一个错误吗?如果不是,是否有一种优先的方式来编写避免这种情况的thunk?在我的实际用例中,menuItem中props的结构非常复杂,在thunk中创建activeItem并在调度到状态树之前改变它的值是很方便的。这样做不好吗?

1 个答案:

答案 0 :(得分:0)

那不是bug,强烈建议不要对state对象进行突变。您可以使用https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign示例部分)中所述的Object.assignJSON.stringify方法创建对象的深层副本。 如果Redux在每个state调用中创建dispatch的深层副本,则可能会更安全,但速度也会慢得多。