【发布时间】:2018-02-04 15:14:29
【问题描述】:
我有一个带有项目菜单的应用程序,并且在某些时候,用户可能会编辑项目的值。当用户这样做时,我会在单独的状态分支中创建该项目的副本,而不是更改原始菜单项。所以我的减速器看起来像这样:
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 中的道具结构非常复杂,在 thunk 中创建一个 activeItem 并在分派到状态树之前改变它的值是很方便的。这样做很糟糕吗?
【问题讨论】:
-
“这会导致 dispatchEditItem thunk 触发并在状态树中创建一个副本” - 我没有看到该代码的哪个部分应该创建一个副本。
-
edtingMenuItem reducer 是副本。
state.menu是 menuItems 的列表,state.editingMenuItem应该是该列表中某个项目的副本。setEditItem填充该副本的值。
标签: javascript redux redux-thunk