我有一个带有项目菜单的应用程序,在某些时候用户可以编辑项目的值。当用户这样做时,我在单独的状态分支中创建项目的副本,而不是更改原始菜单项。所以我的减速机看起来像这样:
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
并在调度到状态树之前改变它的值是很方便的。这样做不好吗?
答案 0 :(得分:0)
那不是bug,强烈建议不要对state
对象进行突变。您可以使用https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign(示例部分)中所述的Object.assign
和JSON.stringify
方法创建对象的深层副本。
如果Redux在每个state
调用中创建dispatch
的深层副本,则可能会更安全,但速度也会慢得多。