这是使用redux删除项目的正确方法吗?

CWr*_*ght 100 javascript reactjs redux

我知道我不应该改变输入,应该克隆对象来改变它.我遵循在redux启动项目中使用的约定,该项目使用:

ADD_ITEM: (state, action) => ({
  ...state,
  items: [...state.items, action.payload.value],
  lastUpdated: action.payload.date
})
Run Code Online (Sandbox Code Playgroud)

添加项目 - 我使用spread来将项目附加到数组中.

删除我用过:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
  lastUpdated: Date.now() 
})
Run Code Online (Sandbox Code Playgroud)

但是这会改变输入状态对象 - 即使我返回一个新对象,这是否被禁止?

Dav*_*lsh 181

不,永远不要改变你的状态.

即使您正在返回一个新对象,您仍然会污染旧对象,这是您永远不想做的事情.这使得在旧状态和新状态之间进行比较时存在问题.例如shouldComponentUpdate,react-redux在引擎盖下使用.它也使得时间旅行变得不可能(即撤消和重做).

相反,使用不可变方法.永远使用Array#slice,永远不要Array#splice.

我假设您的代码action.payload是要删除的项目的索引.更好的方法如下:

items: [
    ...state.items.slice(0, action.payload),
    ...state.items.slice(action.payload + 1)
],
Run Code Online (Sandbox Code Playgroud)

  • `Array#slice`返回一个数组.为了将两个切片组合成一个数组,我使用了扩展运算符.没有它,你将拥有一个数组数组. (5认同)
  • 请用jsfiddle/codepen示例证明.片段`arr.slice(arr.length)`应该总是产生一个空数组,无论`arr`的内容是什么. (4认同)
  • 那讲得通.非常感谢您的澄清(并为最初的困惑感到抱歉). (4认同)

Ste*_*h M 129

您可以使用数组筛选器方法从数组中删除特定元素,而不会改变原始状态.

return state.filter(element => element !== action.payload);
Run Code Online (Sandbox Code Playgroud)

在您的代码的上下文中,它看起来像这样:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => item !== action.payload),
  lastUpdated: Date.now() 
})
Run Code Online (Sandbox Code Playgroud)

  • @chenop是的,Array.filter方法返回一个新数组.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter (5认同)
  • 请注意,如果存在重复项,则会删除所有这些副本.要使用过滤器删除特定索引,可以使用例如`arr.filter((val,i)=> i!== action.payload) (4认同)
  • 你可以在原始问题的上下文中写这个,即提问者在状态中有一个项目数组,而你的答案表明状态纯粹是数组本身. (2认同)

Joe*_*dee 17

ES6 Array.prototype.filter方法返回一个包含与条件匹配的项的新数组.因此,在原始问题的背景下,这将是:

DELETE_ITEM: (state, action) => ({
  ...state,
  items: state.items.filter(item => action.payload !== item),
  lastUpdated: Date.now() 
})
Run Code Online (Sandbox Code Playgroud)


Rom*_*man 9

带有对象的数组的不可变“DELETED”reducer 的另一种变体:

const index = state.map(item => item.name).indexOf(action.name);
const stateTemp = [
  ...state.slice(0, index),
  ...state.slice(index + 1)
];
return stateTemp;
Run Code Online (Sandbox Code Playgroud)