Próbuję uporządkować swój stan za pomocą zagnieżdżonej właściwości w następujący sposób:
this.state = {
someProperty: {
flag:true
}
}
Ale aktualizowanie takiego stanu,
this.setState({ someProperty.flag: false });
nie działa Jak można to zrobić poprawnie?
javascript
reactjs
ecmascript-6
setstate
Alex Yong
źródło
źródło
Odpowiedzi:
W
setState
przypadku zagnieżdżonego obiektu można zastosować poniższe podejście, ponieważ myślę, że setState nie obsługuje zagnieżdżonych aktualizacji.Chodzi o to, aby utworzyć fikcyjny obiekt, wykonać na nim operacje, a następnie zastąpić stan komponentu zaktualizowanym obiektem
Teraz operator rozkładania tworzy tylko jedną zagnieżdżoną kopię obiektu. Jeśli twój stan jest mocno zagnieżdżony, jak:
Możesz ustawić Stan używając operatora spreadu na każdym poziomie jak
Jednak powyższa składnia staje się coraz bardziej brzydka, ponieważ stan staje się coraz bardziej zagnieżdżony, dlatego polecam użyć
immutability-helper
pakietu do aktualizacji stanu.Zobacz tę odpowiedź na temat aktualizacji stanu za pomocą
immutability helper
.źródło
someProperty
i modyfikujemy gothis.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}})
Trochę nudne ......prevState,
w ostatnim przykładzie, tylko tysomeProperty
i jego dzieciAby napisać w jednym wierszu
źródło
this.state
od razusetState
i oczekuj, że będzie miało nową wartość. W porównaniu do połączeńthis.state
wewnątrzsetState
. Czy jest też problem z tym ostatnim, który nie jest dla mnie jasny?this.state
po nimsetState
. Poza tym nie przechodzimythis.state
dosetState
. Te…
właściwości rozprzestrzeniania operatora. Jest taki sam jak Object.assign (). github.com/tc39/proposal-object-rest-spreadthis.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });
może pozwolić uniknąć tego problemu?Czasami bezpośrednie odpowiedzi nie są najlepsze :)
Krótka wersja:
ten kod
należy uprościć jako coś w tym rodzaju
Długa wersja:
Obecnie nie powinieneś chcieć pracować ze stanem zagnieżdżonym w React . Ponieważ React nie jest zorientowany na pracę ze stanami zagnieżdżonymi, a wszystkie proponowane tutaj rozwiązania wyglądają jak hacki. Nie używają frameworka, ale z nim walczą. Sugerują napisanie niezbyt przejrzystego kodu w celu wątpliwego zgrupowania niektórych właściwości. Są więc bardzo interesujące jako odpowiedź na wyzwanie, ale praktycznie bezużyteczne.
Wyobraźmy sobie następujący stan:
Co się stanie, jeśli zmienisz tylko wartość
child1
? React nie renderuje ponownie widoku, ponieważ używa płytkiego porównania i stwierdzi, żeparent
właściwość się nie zmieniła. BTW bezpośrednia mutacja obiektu stanu jest ogólnie uważana za złą praktykę.Musisz więc ponownie stworzyć całość
parent
obiekt. Ale w tym przypadku napotkamy inny problem. React pomyśli, że wszystkie dzieci zmieniły swoje wartości i zrenderuje je wszystkie. Oczywiście nie sprzyja to wydajności.Nadal można rozwiązać ten problem, pisząc skomplikowaną logikę,
shouldComponentUpdate()
ale wolałbym zatrzymać się tutaj i zastosować proste rozwiązanie z krótkiej wersji.źródło
Zrzeczenie się
odpowiedź na twoją nędzę - patrz przykład tutaj
Tam jest inny krótszy sposób aktualizacji dowolnej zagnieżdżonej właściwości.
W jednej linii
Uwaga: tutaj jest operator przecinkowy ~ MDN , zobacz tutaj w akcji (piaskownica) .
To jest podobne do (chociaż to nie zmienia odniesienia stanu)
Dla subtelnej różnicy w tym kontekście między
forceUpdate
isetState
patrz połączony przykład.Oczywiście narusza to niektóre podstawowe zasady, takie jak
state
powinno być tylko do odczytu, ale ponieważ natychmiast odrzucasz stary stan i zastępujesz go nowym, jest to całkowicie w porządku.Ostrzeżenie
Nawet jeśli składnik zawierający stan będzie aktualizować i rerender prawidłowo ( z wyjątkiem tego Gotcha ) , rekwizyty będą nie propagować dzieci (patrz komentarz Spymaster za poniżej) . Użyj tej techniki tylko wtedy, gdy wiesz, co robisz.
Na przykład możesz przekazać zmieniony płaski rekwizyt, który można łatwo zaktualizować i przekazać.
Teraz, mimo że odwołanie do complexNestedProp nie uległo zmianie ( shouldComponentUpdate )
komponent zwróci się ponownie po każdej aktualizacji komponentu nadrzędnego, co ma miejsce po wywołaniu
this.setState
lubthis.forceUpdate
w elemencie nadrzędnym.Skutki mutowania państwa
Korzystanie stan zagnieżdżony i mutowania stan bezpośrednio jest niebezpieczne, ponieważ różne obiekty mogą posiadać (celowo lub nie) różne (starsze) odniesienia do państwa i niekoniecznie musi wiedzieć, kiedy do aktualizacji (przy użyciu na przykład
PureComponent
czyshouldComponentUpdate
jest realizowany do zwrotufalse
) OR są przeznaczony do wyświetlania starych danych, jak w poniższym przykładzie.W każdym razie tutaj możesz zobaczyć,
Nested PureChildClass
że nie został ponownie przesłany z powodu braku propagacji rekwizytów.źródło
state
i używa niestandardowych obserwowalnych właściwości. React'ssetState
to tylko wbudowana wygoda, ale wkrótce zdajesz sobie sprawę, że ma swoje ograniczenia. Korzystanie z niestandardowych właściwości i inteligentne użycieforceUpdate
daje znacznie więcej. Użyj składników Obserwowalne zamiast stanu w komponentach React.this.forceUpdate()
lub zaimplementować określoneshouldComponentUpdate
.Jeśli używasz ES2015, masz dostęp do Object.assign. Możesz użyć go w następujący sposób, aby zaktualizować zagnieżdżony obiekt.
Scalasz zaktualizowane właściwości z istniejącymi i używasz zwróconego obiektu do aktualizacji stanu.
Edycja: Dodano pusty obiekt jako cel do funkcji przypisania, aby upewnić się, że stan nie jest mutowany bezpośrednio, jak wskazał carkod.
źródło
źródło
property
zawiera kilka zagnieżdżonych właściwości, pierwsza usunie je, a druga nie. odesandbox.io/s/nameless-pine-42thuIstnieje wiele bibliotek, które mogą w tym pomóc. Na przykład za pomocą pomocnika niezmienności :
Za pomocą zestawu lodash / fp :
Za pomocą scalania lodash / fp :
źródło
lodash
, prawdopodobnie chcesz spróbować_.cloneDeep
ustawić stan jako klonowaną kopię.lodash/fp
, więc nie musimy się martwić o mutacje.merge
lubset
funkcji w lodash / fp oprócz składni?this.setState(newState)
po metody lodash / fp. Inną gotcha jest to, że lodash.set
(non-fp) ma inną kolejność argumentów, co mnie na chwilę potknęło .Używamy Immer https://github.com/mweststrate/immer do obsługi tego rodzaju problemów.
Właśnie zastąpiłem ten kod w jednym z naszych komponentów
Z tym
Z zanurzeniem traktujesz swój stan jako „normalny obiekt”. Magia dzieje się za sceną z obiektami proxy.
źródło
Oto wariant pierwszej odpowiedzi podanej w tym wątku, który nie wymaga żadnych dodatkowych pakietów, bibliotek ani funkcji specjalnych.
Aby ustawić stan określonego zagnieżdżonego pola, ustawiłeś cały obiekt. Zrobiłem to przez utworzenie zmiennej,
newState
i rozprzestrzenia zawartość aktualnego stanu do niego pierwszy pomocą ES2015 operatora spread . Następnie zastąpiłem wartośćthis.state.flag
nową wartością (ponieważ ustawiłemflag: value
po rozłożeniu bieżącego stanu na obiekt,flag
pole w bieżącym stanie jest zastępowane). Następnie po prostu ustawiam stansomeProperty
mojegonewState
obiektu.źródło
Chociaż zagnieżdżanie nie jest tak naprawdę sposobem traktowania stanu komponentu, czasami dla czegoś łatwego dla zagnieżdżania na jednym poziomie.
Dla takiego stanu
Ponownie używana metoda, którą zastosowałem, wyglądałaby tak.
następnie przekazując nazwę obj dla każdego zagnieżdżenia, do którego chcesz się adresować ...
ź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ń
źródło
Utwórz kopię stanu:
wprowadź zmiany w tym obiekcie:
teraz zaktualizuj stan
źródło
Chociaż pytano o stan opartego na klasach komponentu React, ten sam problem występuje w przypadku hook useState. Co gorsza: hak useState nie akceptuje częściowych aktualizacji. To pytanie stało się bardzo istotne, gdy wprowadzono hook useState.
Postanowiłem opublikować następującą odpowiedź, aby upewnić się, że pytanie obejmuje bardziej nowoczesne scenariusze, w których używany jest haczyk useState:
Jeśli masz:
możesz ustawić zagnieżdżoną właściwość poprzez klonowanie bieżącej i łatanie wymaganych segmentów danych, na przykład:
Lub możesz użyć biblioteki Immer, aby uprościć klonowanie i łatanie obiektu.
Możesz też użyć biblioteki Hookstate (oświadczenie: jestem autorem), aby całkowicie zarządzać złożonymi (lokalnymi i globalnymi) danymi stanu i całkowicie poprawić wydajność (czytaj: nie martw się o optymalizację renderowania):
uzyskaj pole do renderowania:
ustaw zagnieżdżone pole:
Oto przykład Hookstate, w którym stan jest głęboko / rekurencyjnie zagnieżdżony w drzewiastej strukturze danych .
źródło
Dwie inne opcje jeszcze nie wymienione:
źródło
Aby wszystko było ogólne, pracowałem nad odpowiedziami @ ShubhamKhatri i @ Qwerty.
obiekt państwowy
kontrola wejściowa
metoda updateState
setState as @ ShubhamKhatri odpowiedź
setState jako odpowiedź @ Qwerty
Uwaga: powyższe metody nie będą działać dla tablic
źródło
Bardzo poważnie podchodzę do obaw wyrażonych już wokół tworzenia kompletnej kopii stanu twojego komponentu. Powiedziawszy to, zdecydowanie zalecam Immer .
Powinno to działać w przypadku
React.PureComponent
(tzn. Porównań stanu płytkiego React), ponieważImmer
sprytnie wykorzystuje obiekt proxy do wydajnego kopiowania arbitralnie głębokiego drzewa stanu. Immer jest również bardziej bezpieczny dla typów w porównaniu do bibliotek takich jak Immutability Helper i jest idealny dla użytkowników Javascript i maszynopisu.Funkcja narzędzia do pisania
źródło
źródło
obj
jest to tylko odniesienie do stanu, więc poprzez tothis.state
Okazało się, że to działa dla mnie, mając w moim przypadku formularz projektu, w którym na przykład masz identyfikator i nazwę, a raczej wolę zachować stan dla projektu zagnieżdżonego.
Daj mi znać!
źródło
Coś takiego może wystarczyć
źródło
Wiem, że to stare pytanie, ale nadal chciałem podzielić się tym, jak to osiągnąłem. Zakładając, że stan w konstruktorze wygląda następująco:
Moja
handleChange
funkcja jest taka:I pamiętaj, aby odpowiednio nazwać dane wejściowe:
źródło
Aktualizacje zagnieżdżone wykonuję za pomocą wyszukiwania ograniczonego :
Przykład:
Zagnieżdżone zmienne w stanie:
Funkcja:
Posługiwać się:
źródło
To jest mój stan początkowy
Hak lub możesz go zastąpić stanem (komponent klasy)
Metoda handleChange
Metoda ustawiania stanu za pomocą stanów zagnieżdżonych
Wreszcie to jest wejście, którego używam
źródło
Jeśli używasz formik w swoim projekcie, ma to łatwy sposób na obsługę tego. Oto najłatwiejszy sposób na zrobienie z formik.
Najpierw ustaw wartości początkowe w atrybucie formik initivalues lub w reakcji. stan
Tutaj wartości początkowe są definiowane w stanie reakcji
zdefiniuj powyżej wartości początkowe dla pola formik wewnątrz
initiValues
atrybutu formikZrób konsolę, aby sprawdzić stan zaktualizowany w
string
zamiast funkcjiboolean
formik,setFieldValue
aby ustawić stan lub skorzystaj z narzędzia do debugowania Reaguj, aby zobaczyć zmiany w wartościach stanu formik.źródło
spróbuj tego kodu:
źródło
someProperty
i po wykonaniu powyższego koduflag
pozostaną tylko właściwościw książce widziałem:
ale nie jestem pewien, czy to prawda ..
źródło