Czy w ogóle można aktualizować właściwości obiektu setState
?
Coś jak:
this.state = {
jasper: { name: 'jasper', age: 28 },
}
Próbowałem:
this.setState({jasper.name: 'someOtherName'});
i to:
this.setState({jasper: {name: 'someothername'}})
Pierwszy powoduje błąd składniowy, a drugi po prostu nic nie robi. Jakieś pomysły?
age
właściwość w środkujasper
.Odpowiedzi:
Istnieje wiele sposobów, aby to zrobić, ponieważ zmiana stanu jest praca asynchroniczny , tak aby zaktualizować stan obiektu, musimy użyć Updater funkcji z
setState
.1- najprostszy:
Najpierw utwórz kopię,
jasper
a następnie wykonaj następujące zmiany:Zamiast używać
Object.assign
możemy również napisać to w ten sposób:2- Korzystanie z operatora rozrzucania :
Uwaga:
Object.assign
iSpread Operator
tworzy tylko płytką kopię , więc jeśli zdefiniowałeś zagnieżdżony obiekt lub tablicę obiektów, potrzebujesz innego podejścia.Aktualizowanie zagnieżdżonego obiektu stanu:
Załóżmy, że zdefiniowałeś stan jako:
Aby zaktualizować obiekt extraCheese pizzy:
Aktualizowanie tablicy obiektów:
Załóżmy, że masz aplikację do zrobienia i zarządzasz danymi w tej formie:
Aby zaktualizować status dowolnego obiektu do zrobienia, uruchom mapę w tablicy i sprawdź, czy dla każdego obiektu jest jakaś unikalna wartość, w przypadku
condition=true
zwrócenia nowego obiektu ze zaktualizowaną wartością, w innym przypadku tego samego obiektu.Sugestia: Jeśli obiekt nie ma unikalnej wartości, użyj indeksu tablicy.
źródło
jasper
obiektu, czyconsole.log(jasper)
zobaczysz tylko jeden kluczname
, wiek nie będzie tam :)jasper
jestobject
, czy nie jest najlepsza czy nie, mogą być możliwe inne lepsze rozwiązania :)Object.assign
nie kopiują właściwości głębokiego kopiowania przez operatora. W ten sposób powinieneś zastosować obejścia takie jak lodashdeepCopy
itp.let { jasper } = this.state
?Jest to najszybszy i najbardziej czytelny sposób:
Nawet jeśli
this.state.jasper
już zawiera właściwość name,name: 'someothername'
należy użyć nowej nazwy .źródło
this.state.jasper
niekoniecznie zawiera najnowszy stan. Lepiej użyj notacji zprevState
.Użyj operatora rozprzestrzeniania i trochę ES6 tutaj
źródło
Użyłem tego rozwiązania.
Jeśli masz taki stan zagnieżdżenia:
możesz zadeklarować funkcję handleChange, która kopiuje bieżący status i przypisuje go ponownie ze zmienionymi wartościami
tutaj HTML z detektorem zdarzeń. Upewnij się, że używasz tej samej nazwy, co nazwa obiektu stanu (w tym przypadku „friendName”)
źródło
statusCopy.formInputs[inputName] = inputValue;
Wiem, że jest tu wiele odpowiedzi, ale jestem zaskoczony, że żadna z nich nie tworzy kopii nowego obiektu poza setState, a następnie po prostu setState ({newObject}). Czysty, zwięzły i niezawodny. Więc w tym przypadku:
Lub dla właściwości dynamicznej (bardzo przydatne w przypadku formularzy)
źródło
spróbuj tego, powinno działać dobrze
źródło
Object.assign({}, this.state.jasper, {name:'someOtherName'})
Pierwszy przypadek to rzeczywiście błąd składniowy.
Ponieważ nie widzę reszty twojego komponentu, trudno jest zrozumieć, dlaczego tutaj zagnieżdżasz obiekty w swoim stanie. Nie jest dobrym pomysłem zagnieżdżanie obiektów w stanie komponentu. Spróbuj ustawić swój stan początkowy na:
W ten sposób, jeśli chcesz zaktualizować nazwę, możesz po prostu zadzwonić:
Czy osiągniesz to, do czego dążysz?
W przypadku większych, bardziej złożonych magazynów danych użyłbym czegoś takiego jak Redux. Ale to znacznie bardziej zaawansowane.
Ogólna reguła dotycząca stanu komponentu polega na używaniu go tylko do zarządzania stanem interfejsu użytkownika komponentu (np. Aktywny, timery itp.)
Sprawdź te referencje:
źródło
Inna opcja: zdefiniuj zmienną z obiektu Jasper, a następnie po prostu wywołaj zmienną.
Operator rozrzutu: ES6
źródło
Prosty i dynamiczny sposób.
Wykona to zadanie, ale musisz ustawić wszystkie identyfikatory nadrzędne, aby rodzic wskazywał nazwę obiektu, id = "jasper" i nazwał nazwę elementu wejściowego = właściwość wewnątrz obiektu jasper .
źródło
Możesz spróbować z tym : ( Uwaga : nazwa znacznika wejściowego === pole obiektu)
źródło
to jest inne rozwiązanie używając immer narzędzia immutabe, bardzo nadaje się do głęboko zagnieżdżonych obiektów z łatwością, a ty nie powinien dbać o mutacji
źródło
Ponadto, postępując zgodnie z rozwiązaniem Alberto Pirasa, jeśli nie chcesz skopiować całego obiektu „stanowego”:
źródło
Możesz spróbować z tym:
lub w przypadku innej nieruchomości:
Lub możesz użyć funkcji handleChage:
i kod HTML:
źródło
Bez użycia Async i Oczekuj Użyj tego ...
Jeśli korzystasz z Async i Oczekuj, użyj tego ...
źródło
Ta konfiguracja działała dla mnie:
źródło