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

6qqygrtg  于 2023-06-22  发布在  React
关注(0)|答案(7)|浏览(132)

我知道我不应该改变输入,应该克隆对象来改变它。我遵循了redux starter项目中使用的约定,其中使用:

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() 
})

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

ocebsuys

ocebsuys1#

不,永远不要改变你的状态。
即使你返回了一个新对象,你仍然会污染旧对象,这是你永远不想做的。这使得在进行旧状态和新状态之间的比较时存在问题。例如react-redux在引擎盖下使用的shouldComponentUpdate中。它也使时间旅行成为不可能(即。撤消和重做)。
相反,使用不可变的方法。始终使用Array#slice,永远不要使用Array#splice
从代码中我假设action.payload是要删除的项的索引。更好的方法如下:

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

bwntbbo32#

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

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

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

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

vwhgwdsa3#

ES6 Array.prototype.filter方法返回一个新数组,其中包含与条件匹配的项。因此,就原质询而言,这是:

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

tf7tbtn24#

另一个不可变的“DELETED”reducer的变体,用于具有对象的数组:

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

mkshixfv5#

以不同的方式使用redux删除项目。
方法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;
               }

方法2:在这种情况下使用switch(...),spread-operator

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

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

对于初始化此状态的两个方法:

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

vlurs2pr6#

黄金法则是我们不会返回变异状态,而是返回新状态。根据操作的类型,当它到达reducer时,您可能需要以各种形式更新状态树。
在这个场景中,我们试图从状态属性中删除一个项目。
这就引出了Redux的不可变更新(或数据修改)模式的概念。不变性是关键,因为我们从来不想直接改变状态树中的值,而是总是复制并基于旧值返回一个新值。
下面是一个如何删除嵌套对象的示例:

// 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;
  }
}

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

8qgya5xd

8qgya5xd7#

从数组中不可变地/功能性地删除index处的元素:

items: [
    ...items.slice(0, index),
    ...items.slice(index + 1)
]

或者更简单(也可能更快):

items: items.filter((_, i) => i !== index)

相关问题