Mam następującą strukturę:
FormEditor
- posiada wiele FieldEditor
FieldEditor
- edytuje pole formularza i zapisuje różne wartości na jego temat w jego stanie
Po kliknięciu przycisku w formularzu FormEditor chcę być w stanie zebrać informacje o polach ze wszystkich FieldEditor
składników, informacje w ich stanie i mieć je wszystkie w formularzu FormEditor.
Rozważyłem przechowywanie informacji o polach poza FieldEditor
stanem i FormEditor
zamiast tego umieściłem je w stanie. Wymagałoby FormEditor
to jednak wysłuchania każdego z jego FieldEditor
składników, gdy zmieniają się i przechowują informacje w tym stanie.
Czy nie mogę po prostu uzyskać dostępu do stanu dzieci? Czy to jest idealne?
javascript
reactjs
Moshe Revah
źródło
źródło
FieldEditor
s osobno, zapisywanie ich stanu wFormEditor
dobrym brzmieniu. W takim przypadkuFieldEditor
instancje będą renderowane na podstawieprops
przekazanych przez ich edytor formularzy, a nie ichstate
. Bardziej złożonym, ale elastycznym sposobem byłoby utworzenie serializatora, który przechodzi przez dowolne elementy potomne kontenera i znajduje wszystkieFormEditor
wystąpienia między nimi i serializuje je do obiektu JSON. Obiekt JSON może być opcjonalnie zagnieżdżony (więcej niż jeden poziom) na podstawie poziomów zagnieżdżenia instancji w edytorze formularzy.Odpowiedzi:
Jeśli masz już moduł obsługi onChange dla poszczególnych FieldEditors, nie rozumiem, dlaczego nie możesz po prostu przenieść stanu do komponentu FormEditor i po prostu przekazać stamtąd wywołanie zwrotne do FieldEditors, które zaktualizują stan nadrzędny. Dla mnie to wydaje się bardziej reaktywnym sposobem.
Być może coś w tym rodzaju:
Oryginał - wersja z zaczepami:
Pokaż fragment kodu
źródło
myAPI.SaveStuff(this.state);
. Jeśli opracujesz trochę więcej, może dam ci lepszą odpowiedź :)Zanim przejdę do szczegółów na temat uzyskiwania dostępu do stanu elementu potomnego, przeczytaj odpowiedź Markusa-ipse dotyczącą lepszego rozwiązania tego konkretnego scenariusza.
Jeśli rzeczywiście chcesz uzyskać dostęp do stanu elementów potomnych komponentu, możesz przypisać właściwość wywoływaną
ref
dla każdego elementu potomnego. Istnieją teraz dwa sposoby implementacji referencji: Korzystanie z referencjiReact.createRef()
i wywołanie zwrotne.Za pomocą
React.createRef()
Jest to obecnie zalecany sposób używania referencji od React 16.3 ( Więcej informacji można znaleźć w dokumentacji ). Jeśli używasz wcześniejszej wersji, zapoznaj się z poniższymi informacjami na temat odwołań zwrotnych.
Musisz utworzyć nowe odwołanie w konstruktorze komponentu nadrzędnego, a następnie przypisać je do elementu podrzędnego za pomocą
ref
atrybutu.Aby uzyskać dostęp do tego rodzaju referencji, musisz użyć:
Zwróci to instancję zamontowanego komponentu, abyś mógł następnie użyć,
currentFieldEditor1.state
aby uzyskać dostęp do stanu.Krótka uwaga, aby powiedzieć, że jeśli użyjesz tych odniesień w węźle DOM zamiast w komponencie (np.
<div ref={this.divRef} />
), Wówczasthis.divRef.current
zwróci podstawowy element DOM zamiast instancji komponentu.Oddzwanianie
Ta właściwość przyjmuje funkcję wywołania zwrotnego, która jest przekazywana do dołączonego komponentu. To wywołanie zwrotne jest wykonywane natychmiast po zamontowaniu lub odmontowaniu komponentu.
Na przykład:
W tych przykładach odwołanie jest przechowywane w komponencie nadrzędnym. Aby wywołać ten składnik w kodzie, możesz użyć:
a następnie użyj,
this.fieldEditor1.state
aby uzyskać stan.Należy zwrócić uwagę na jedną rzecz: upewnij się, że komponent potomny jest renderowany, zanim spróbujesz uzyskać do niego dostęp ^ ^ ^
Jak wyżej, jeśli użyjesz tych odniesień w węźle DOM zamiast w komponencie (np.
<div ref={(divRef) => {this.myDiv = divRef;}} />
), Wówczasthis.divRef
zwróci podstawowy element DOM zamiast instancji komponentu.Dalsza informacja
Jeśli chcesz dowiedzieć się więcej o nieruchomości referencyjnej React, sprawdź tę stronę na Facebooku.
Upewnij się, że przeczytałeś sekcję „ Nie nadużywaj referencji ”, która mówi, że nie powinieneś używać dziecka
state
do „sprawiania, by coś się działo”.Mam nadzieję, że to pomoże ^ _ ^
Edycja: Dodano
React.createRef()
metodę tworzenia referencji. Usunięto kod ES5.źródło
this.refs.yourComponentNameHere
. Uznałem, że jest to przydatne do zmiany stanu za pomocą funkcji. Przykład:this.refs.textInputField.clearInput();
props
istate
. Nie powinny one jednak służyć jako abstrakcja dla przepływających danych przez aplikację. Domyślnie użyj Reaktywnego przepływu danych i zapiszref
s dla przypadków użycia, które z natury nie są reaktywne.connected
składnikiem Redux ?Jest rok 2020 i wielu z was przyjedzie tutaj, szukając podobnego rozwiązania, ale z Hakami (są świetne!) I najnowszymi podejściami pod względem czystości kodu i składni.
Tak więc, jak stwierdzono w poprzednich odpowiedziach, najlepszym podejściem do tego rodzaju problemu jest utrzymywanie stanu poza komponentem potomnym
fieldEditor
. Możesz to zrobić na wiele sposobów.Najbardziej „skomplikowany” jest kontekst globalny (stan), do którego zarówno rodzic, jak i dziecko mogą uzyskać dostęp i modyfikować. To świetne rozwiązanie, gdy komponenty znajdują się bardzo głęboko w hierarchii drzew, a zatem kosztowne jest wysyłanie rekwizytów na każdym poziomie.
W tym przypadku uważam, że nie jest tego warte, a prostsze podejście przyniesie nam pożądane wyniki, używając tylko potężnego
React.useState()
.Podejdź do haka React.useState (), znacznie prościej niż przy komponentach Class
Jak już powiedzieliśmy, zajmiemy się zmianami i będziemy przechowywać dane naszego elementu potomnego
fieldEditor
w naszym rodzicufieldForm
. Aby to zrobić, wyślemy referencję do funkcji, która zajmie się zmianamifieldForm
stanu i zastosuje je , możesz to zrobić za pomocą:Zauważ, że
React.useState({})
zwróci tablicę z pozycją 0 będącą wartością określoną podczas wywołania (w tym przypadku pusty obiekt), a pozycja 1 będzie odniesieniem do funkcji, która modyfikuje wartość.Teraz dzięki komponentowi
FieldEditor
potomnemu nie musisz nawet tworzyć funkcji z instrukcją return, wystarczy stała stała z funkcją strzałki!Aaaaaaaaaaaaaaaaaaaaaa, i nic więcej, tylko te dwa śluzowe elementy funkcjonalne mają nasz cel końcowy „dostęp” do naszej
FieldEditor
wartości dla dziecka i pokazanie jej u naszego rodzica.Możesz sprawdzić zaakceptowaną odpowiedź sprzed 5 lat i zobaczyć, w jaki sposób Hooks sprawił, że kod React był węższy (o wiele!).
Mam nadzieję, że moja odpowiedź pomoże Ci dowiedzieć się i zrozumieć więcej o Hakach, a jeśli chcesz sprawdzić działający przykład, oto ona .
źródło
Teraz możesz uzyskać dostęp do stanu InputField, który jest potomkiem FormEditor.
Zasadniczo za każdym razem, gdy następuje zmiana stanu pola wejściowego (dziecko), otrzymujemy wartość z obiektu zdarzenia, a następnie przekazujemy tę wartość do obiektu nadrzędnego, w którym ustawiony jest stan w obiekcie nadrzędnym.
Po kliknięciu przycisku drukujemy tylko stan pól wejściowych.
Kluczową kwestią jest to, że używamy rekwizytów, aby uzyskać identyfikator / wartość pola wejściowego, a także wywołać funkcje ustawione jako atrybuty w polu wejściowym podczas generowania potomnych pól wejściowych wielokrotnego użytku.
źródło
Jak powiedziano w poprzednich odpowiedziach, spróbuj przenieść stan do najwyższego komponentu i zmodyfikuj go przez wywołania zwrotne przekazywane do jego dzieci.
Jeśli naprawdę potrzebujesz dostępu do stanu potomnego zadeklarowanego jako składnik funkcjonalny (przechwytuje), możesz zadeklarować ref w komponencie nadrzędnym, a następnie przekazać go jako atrybut ref do dziecka, ale musisz użyć React.forwardRef a następnie hook użyjImperativeHandle, aby zadeklarować funkcję, którą możesz wywołać w komponencie nadrzędnym.
Spójrz na następujący przykład:
Następnie powinieneś być w stanie uzyskać myState w komponencie Parent, wywołując:
myRef.current.getMyState();
źródło