简体   繁体   English

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

[英]Is this the correct way to delete an item using redux?

I know I'm not supposed to mutate the input and should clone the object to mutate it.我知道我不应该改变输入,应该克隆对象来改变它。 I was following the convention used on a redux starter project which used:我遵循 redux starter 项目中使用的约定,该项目使用了:

ADD_ITEM: (state, action) => ({
  ...state,
  items: [...state.items, action.payload.value],
  lastUpdated: action.payload.date
})

for adding an item - I get the use of spread to append the item in the array.添加项目 - 我使用 spread 将项目附加到数组中。

for deleting I used:删除我用过:

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

but this is mutating the input state object - is this forbidden even though I am returning a new object?但这正在改变输入状态对象 - 即使我返回一个新对象,这是否被禁止?

No. Never mutate your state.不。永远不要改变你的状态。

Even though you're returning a new object, you're still polluting the old object, which you never want to do.即使您返回了一个新对象,您仍然在污染旧对象,这是您永远不想做的。 This makes it problematic when doing comparisons between the old and the new state.这使得在旧状态和新状态之间进行比较时会出现问题。 For instance in shouldComponentUpdate which react-redux uses under the hood.例如,在 react-redux shouldComponentUpdate使用的shouldComponentUpdate中。 It also makes time travel impossible (ie undo and redo).它还使时间旅行变得不可能(即撤消和重做)。

Instead, use immutable methods.相反,使用不可变的方法。 Always use Array#slice and never Array#splice .始终使用Array#slice而永远不要使用Array#splice

I assume from your code that action.payload is the index of the item being removed.我从你的代码中假设action.payload是被删除项目的索引。 A better way would be as follows:更好的方法如下:

items: [
    ...state.items.slice(0, action.payload),
    ...state.items.slice(action.payload + 1)
],

You can use the array filter method to remove a specific element from an array without mutating the original state.您可以使用数组过滤器方法从数组中删除特定元素而不改变原始状态。

return state.filter(element => element !== action.payload);

In the context of your code, it would look something like this:在您的代码上下文中,它看起来像这样:

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

The ES6 Array.prototype.filter method returns a new array with the items that match the criteria. ES6 Array.prototype.filter方法返回一个包含符合条件的项目的新数组。 Therefore, in the context of the original question, this would be:因此,在原始问题的上下文中,这将是:

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

Another one variation of the immutable "DELETED" reducer for the array with objects:带有对象的数组的不可变“DELETED”reducer 的另一种变体:

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

The golden rule is that we do not return a mutated state, but rather a new state.黄金法则是我们不返回突变状态,而是返回一个新状态。 Depending on the type of your action, you might need to update your state tree in various forms when it hits the reducer.根据操作的类型,您可能需要在遇到减速器时以各种形式更新状态树。

In this scenario we are trying to remove an item from a state property.在这种情况下,我们试图从状态属性中删除一个项目。

This brings us to the concept of Redux's immutable update (or data modification) patterns.这让我们想到了 Redux 的不可变更新(或数据修改)模式的概念。 Immutability is key because we never want to directly change a value in the state tree, but rather always make a copy and return a new value based on the old value.不变性是关键,因为我们从不想直接更改状态树中的值,而是始终根据旧值进行复制并返回新值。

Here is an example of how to delete a nested object:以下是如何删除嵌套对象的示例:

 // ducks/outfits (Parent) // types export const NAME = `@outfitsData`; export const REMOVE_FILTER = `${NAME}/REMOVE_FILTER`; // initialization const initialState = { isInitiallyLoaded: false, outfits: ['Outfit.1', 'Outfit.2'], filters: { brand: [], colour: [], }, error: '', }; // action creators export function removeFilter({ field, index }) { return { type: REMOVE_FILTER, field, index, }; } export default function reducer(state = initialState, action = {}) { sswitch (action.type) { case REMOVE_FILTER: return { ...state, filters: { ...state.filters, [action.field]: [...state.filters[action.field]] .filter((x, index) => index !== action.index) }, }; default: return state; } }

To understand this better, make sure to check out this article: https://medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da为了更好地理解这一点,请务必查看这篇文章: https : //medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da

Deleting an item using redux in different ways.使用 redux 以不同方式删除项目。

Method 1: In that case is used createSlice ( .. )方法 1:在这种情况下使用createSlice ( .. )

const { id } = action.payload; // destruct id
removeCart: (state, action) =>{
                 let { id } = action.payload;
                 let arr = state.carts.filter(item => item.id !== parseInt(id))
                 state.carts = arr;
               }

Method 2: In that case is used switch (... ), spread-operator方法 2:在这种情况下使用switch (... ), spread-operator

const { id } = action.payload; // destruct id

case actionTypes.DELETE_CART:  
     return {
        ...state,
        carts: state.carts.filter((item) => item.id !== payload)
      };

For both methods initialized this state:对于这两种方法都初始化了这个状态:

  initialState: {
      carts: ProductData, // in productData mocked somedata     
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM