Eu sei que não devo alterar a entrada e devo clonar o objeto para alterá-lo. Eu estava seguindo a convenção usada em um projeto redux starter que usava:
ADD_ITEM: (state, action) => ({
...state,
items: [...state.items, action.payload.value],
lastUpdated: action.payload.date
})
para adicionar um item - eu uso o spread para anexar o item ao array.
para excluir usei:
DELETE_ITEM: (state, action) => ({
...state,
items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
lastUpdated: Date.now()
})
mas isso está alterando o objeto de estado de entrada - isso é proibido, embora eu esteja retornando um novo objeto?
javascript
reactjs
redux
CWright
fonte
fonte
items: [...state.items.slice(0, action.payload.value), ...state.items.slice(action.payload.value + 1 )]
usar slice agora em vez de splice para não alterar a entrada - esse é o caminho a seguir ou existe um modo mais conciso?Respostas:
Não. Nunca mude seu estado.
Mesmo que você esteja retornando um novo objeto, você ainda está poluindo o objeto antigo, o que você nunca quer fazer. Isso o torna problemático ao fazer comparações entre o antigo e o novo estado. Por exemplo, em
shouldComponentUpdate
que react-redux usa sob o capô. Também torna a viagem no tempo impossível (ou seja, desfazer e refazer).Em vez disso, use métodos imutáveis. Sempre use
Array#slice
e nuncaArray#splice
.Presumo pelo seu código que
action.payload
seja o índice do item que está sendo removido. A melhor maneira seria a seguinte:fonte
...
na segunda instrução dobrará o conteúdo do seu estadoarr.slice(arr.length)
sempre deve produzir um array vazio, não importa qual seja o conteúdoarr
....
na segunda parte -...state.items.slice(action.payload + 1)
Array#slice
retorna uma matriz. Para combinar as duas fatias em uma única matriz, usei o operador spread. Sem ele, você teria uma variedade de matrizes.Você pode usar o método de filtro de matriz para remover um elemento específico de uma matriz sem alterar o estado original.
No contexto do seu código, seria mais ou menos assim:
fonte
arr.filter((val, i) => i !== action.payload )
O
Array.prototype.filter
método ES6 retorna uma nova matriz com os itens que correspondem aos critérios. Portanto, no contexto da pergunta original, seria:fonte
.filter()
não é um método ES2015, mas foi adicionado na versão anterior ES5.Outra variação do redutor "DELETED" imutável para a matriz com objetos:
fonte
A regra de ouro é que não retornamos um estado de mutação, mas sim um novo estado. Dependendo do tipo de sua ação, pode ser necessário atualizar sua árvore de estados de várias formas quando ela atingir o redutor.
Neste cenário, estamos tentando remover um item de uma propriedade de estado.
Isso nos leva ao conceito de padrões imutáveis de atualização (ou modificação de dados) do Redux. A imutabilidade é fundamental porque nunca queremos alterar diretamente um valor na árvore de estado, mas sempre fazer uma cópia e retornar um novo valor com base no valor antigo.
Aqui está um exemplo de como excluir um objeto aninhado:
Para entender melhor isso, certifique-se de verificar este artigo: https://medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da
fonte