我知道我不应该改变输入,应该克隆对象来改变它.我遵循在redux启动项目中使用的约定,该项目使用:
ADD_ITEM: (state, action) => ({ ...state, items: [...state.items, action.payload.value], lastUpdated: action.payload.date })
添加项目 - 我使用spread来将项目附加到数组中.
删除我用过:
DELETE_ITEM: (state, action) => ({ ...state, items: [...state.items.splice(0, action.payload), ...state.items.splice(1)], lastUpdated: Date.now() })
但是这会改变输入状态对象 - 即使我返回一个新对象,这是否被禁止?
不,永远不要改变你的状态.
即使您正在返回一个新对象,您仍然会污染旧对象,这是您永远不想做的事情.这使得在旧状态和新状态之间进行比较时存在问题.例如shouldComponentUpdate
,react-redux在引擎盖下使用.它也使得时间旅行变得不可能(即撤消和重做).
相反,使用不可变方法.永远使用Array#slice
,永远不要Array#splice
.
我假设您的代码action.payload
是要删除的项目的索引.更好的方法如下:
items: [ ...state.items.slice(0, action.payload), ...state.items.slice(action.payload + 1) ],
您可以使用数组筛选器方法从数组中删除特定元素,而不会改变原始状态.
return state.filter(element => element !== action.payload);
在您的代码的上下文中,它看起来像这样:
DELETE_ITEM: (state, action) => ({ ...state, items: state.items.filter(item => item !== action.payload), lastUpdated: Date.now() })
ES6 Array.prototype.filter
方法返回一个包含与条件匹配的项的新数组.因此,在原始问题的背景下,这将是:
DELETE_ITEM: (state, action) => ({ ...state, items: state.items.filter(item => action.payload !== item), lastUpdated: Date.now() })