入力を変更することは想定されていないため、オブジェクトを複製して変更する必要があります。私は以下を使用するreduxスタータープロジェクトで使用される規則に従っていました。
ADD_ITEM: (state, action) => ({
...state,
items: [...state.items, action.payload.value],
lastUpdated: action.payload.date
})
アイテムを追加するために-私はスプレッドを使用して配列にアイテムを追加します。
削除のために私が使用しました:
DELETE_ITEM: (state, action) => ({
...state,
items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
lastUpdated: Date.now()
})
しかし、これは入力状態オブジェクトを変化させています-新しいオブジェクトを返しているにもかかわらず、これは禁止されていますか?
いいえ。自分の状態を変更しないでください。
新しいオブジェクトを返している場合でも、古いオブジェクトを汚染しているため、決して実行したくありません。これにより、古い状態と新しい状態を比較するときに問題が生じます。たとえば、react-reduxが内部で使用するshouldComponentUpdate
の場合。また、タイムトラベルが不可能になります(つまり、元に戻すとやり直し)。
代わりに、不変のメソッドを使用します。常に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()
})
オブジェクトを含む配列の不変の「DELETED」レデューサーのもう1つのバリエーション:
const index = state.map(item => item.name).indexOf(action.name);
const stateTemp = [
...state.slice(0, index),
...state.slice(index + 1)
];
return stateTemp;