Wiem, że nie powinienem modyfikować danych wejściowych i powinienem sklonować obiekt, aby go zmutować. Postępowałem zgodnie z konwencją stosowaną w projekcie startowym Redux, w której zastosowano:
ADD_ITEM: (state, action) => ({
...state,
items: [...state.items, action.payload.value],
lastUpdated: action.payload.date
})
za dodanie pozycji - uzyskuję użycie spreadu, aby dołączyć pozycję do tablicy.
do usunięcia użyłem:
DELETE_ITEM: (state, action) => ({
...state,
items: [...state.items.splice(0, action.payload), ...state.items.splice(1)],
lastUpdated: Date.now()
})
ale to jest mutacja obiektu stanu wejściowego - czy jest to zabronione, mimo że zwracam nowy obiekt?
javascript
reactjs
redux
CWright
źródło
źródło
items: [...state.items.slice(0, action.payload.value), ...state.items.slice(action.payload.value + 1 )]
użyj teraz plastra zamiast łączenia, aby nie modyfikować wejścia - czy to jest droga, czy jest bardziej zwięzła droga?Odpowiedzi:
Nie. Nigdy nie zmieniaj swojego stanu.
Nawet jeśli zwracasz nowy obiekt, nadal zanieczyszczasz stary obiekt, czego nigdy nie chcesz robić. To sprawia, że porównywanie starego i nowego stanu jest problematyczne. Na przykład,
shouldComponentUpdate
gdy reaktor-redux stosuje się pod maską. Uniemożliwia również podróże w czasie (tj. Cofanie i ponawianie).Zamiast tego użyj niezmiennych metod. Zawsze używaj
Array#slice
i nigdyArray#splice
.Zakładam, że z twojego kodu
action.payload
jest indeks usuwanego elementu. Lepszy sposób wyglądałby następująco:źródło
...
w drugiej instrukcji podwoi zawartość twojego stanuarr.slice(arr.length)
powinien zawsze dawać pustą tablicę, bez względu na zawartośćarr
....
w drugiej części -...state.items.slice(action.payload + 1)
Array#slice
zwraca tablicę. Aby połączyć dwa wycinki w jedną tablicę, użyłem operatora spreadu. Bez tego miałbyś tablicę tablic.Możesz użyć metody filtru tablicy, aby usunąć określony element z tablicy bez modyfikowania oryginalnego stanu.
W kontekście twojego kodu wyglądałoby to mniej więcej tak:
źródło
arr.filter((val, i) => i !== action.payload )
Metoda ES6
Array.prototype.filter
zwraca nową tablicę z elementami spełniającymi kryteria. Dlatego w kontekście pierwotnego pytania byłoby to:źródło
.filter()
nie jest metodą ES2015, ale została dodana w poprzedniej wersji ES5.Kolejna odmiana niezmiennego reduktora „DELETED” dla tablicy z obiektami:
źródło
Złota zasada mówi, że nie przywracamy stanu zmutowanego, ale raczej nowy stan. W zależności od rodzaju akcji może być konieczne zaktualizowanie drzewa stanu w różnych formach, gdy trafi ono w reduktor.
W tym scenariuszu próbujemy usunąć element z właściwości stanu.
To prowadzi nas do koncepcji niezmiennych wzorców aktualizacji (lub modyfikacji danych) Redux. Niezmienność jest kluczowa, ponieważ nigdy nie chcemy bezpośrednio zmieniać wartości w drzewie stanów, ale raczej zawsze wykonujemy kopię i zwracamy nową wartość na podstawie starej wartości.
Oto przykład, jak usunąć zagnieżdżony obiekt:
Aby lepiej to zrozumieć, zapoznaj się z tym artykułem: https://medium.com/better-programming/deleting-an-item-in-a-nested-redux-state-3de0cb3943da
źródło