Я знаю, что я не должен изменять ввод и должен клонировать объект, чтобы изменить его. Я следовал соглашению, используемому в стартовом проекте 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()
})
но это изменяет объект состояния ввода - это запрещено, даже если я возвращаю новый объект?
javascript
reactjs
redux
CWright
источник
источник
items: [...state.items.slice(0, action.payload.value), ...state.items.slice(action.payload.value + 1 )]
теперь использовать срез вместо сращивания, чтобы не изменять ввод - это путь или есть более краткий способ?Ответы:
Нет. Никогда не изменяйте свое состояние.
Даже если вы возвращаете новый объект, вы все равно загрязняете старый объект, чего никогда не стоит делать. Это затрудняет сравнение старого и нового состояния. Например, в
shouldComponentUpdate
котором react-redux используется под капотом. Это также делает невозможным путешествие во времени (то есть отмену и повтор).Вместо этого используйте неизменяемые методы. Всегда используйте
Array#slice
и никогдаArray#splice
.Я предполагаю из вашего кода, что
action.payload
это индекс удаляемого элемента. Лучше было бы следующее:источник
...
во втором выражении удвоит содержимое вашего состоянияarr.slice(arr.length)
всегда должен создавать пустой массив, независимо от его содержимогоarr
....
во второй части...state.items.slice(action.payload + 1)
Array#slice
возвращает массив. Чтобы объединить два фрагмента в один массив, я использовал оператор распространения. Без него у вас был бы массив массивов.Вы можете использовать метод фильтрации массива, чтобы удалить определенный элемент из массива без изменения исходного состояния.
В контексте вашего кода это будет выглядеть примерно так:
источник
arr.filter((val, i) => i !== action.payload )
Метод ES6
Array.prototype.filter
возвращает новый массив с элементами, соответствующими критериям. Следовательно, в контексте исходного вопроса это будет:источник
.filter()
не является методом ES2015, но был добавлен в предыдущей версии ES5.Еще один вариант неизменного редуктора DELETED для массива с объектами:
источник
Золотое правило состоит в том, что мы возвращаем не мутированное состояние, а новое состояние. В зависимости от типа вашего действия вам может потребоваться обновить дерево состояний в различных формах, когда оно попадет в редуктор.
В этом сценарии мы пытаемся удалить элемент из свойства состояния.
Это подводит нас к концепции неизменяемых паттернов обновления (или модификации данных) Redux. Неизменяемость является ключевым моментом, потому что мы никогда не хотим напрямую изменять значение в дереве состояний, а всегда делаем копию и возвращаем новое значение на основе старого значения.
Вот пример того, как удалить вложенный объект:
Чтобы лучше понять это, обязательно ознакомьтесь с этой статьей: https://medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da
источник