Globalne tworzenie stanów może spowolnić działanie aplikacji. Dowiedz się, jak efektywnie tworzyć i wykorzystywać stany w aplikacji React.

Jeśli napisałeś dużo kodu React, prawdopodobnie użyłeś niepoprawnie stanu. Częstym błędem popełnianym przez wielu programistów Reacta jest przechowywanie stanów globalnie w aplikacji, zamiast przechowywania ich w komponentach, w których są używane.

Dowiedz się, jak zrefaktoryzować swój kod, aby wykorzystać stan lokalny i dlaczego jest to zawsze dobry pomysł.

Podstawowy przykład stanu w React

Oto bardzo prosta aplikacja licznika który ilustruje typową obsługę stanu w React:

import {useState} z'reagować'
import {Lada} z'lada'

funkcjonowaćAplikacja(){
konst [liczba, ustawLiczba] = użyjStan(0)
powrót<Ladaliczyć={liczyć}liczba ustaw={setCount} />
}

eksportdomyślny Aplikacja

W wierszach 1 i 2 importujesz plik useState() hak do tworzenia stanu i Lada część. Ty definiujesz liczyć stan i liczba ustaw sposób aktualizacji stanu. Następnie przekazujesz oba do Lada część.

The

Lada komponent następnie renderuje plik liczyć i dzwoni liczba ustaw zwiększać i zmniejszać liczbę.

funkcjonowaćLada({count, setCount}) {
powrót (

Nie określiłeś tzw liczyć zmienna i liczba ustaw działać lokalnie wewnątrz Lada część. Zamiast tego przekazałeś go z komponentu nadrzędnego (Aplikacja). Innymi słowy, używasz stanu globalnego.

Problem z państwami globalnymi

Problem z używaniem stanu globalnego polega na tym, że przechowujesz stan w komponencie nadrzędnym (lub rodzicu rodzica), a następnie przekazując to jako rekwizyty do komponentu, w którym ten stan jest faktycznie potrzebny.

Czasami jest to w porządku, gdy masz stan, który jest współdzielony przez wiele komponentów. Ale w tym przypadku żaden inny komponent nie dba o to liczyć stan z wyjątkiem Lada część. Dlatego lepiej przenieść stan do Lada składnika, w którym jest faktycznie używany.

Przenoszenie stanu do komponentu potomnego

Kiedy przeniesiesz stan do Lada komponent, wyglądałoby to tak:

import {useState} z'reagować'

funkcjonowaćLada() {
konst [liczba, ustawLiczba] = użyjStan(0)
powrót (


Następnie w twoim Aplikacja komponent, nie musisz niczego przekazywać do Lada część:

// import
funkcjonowaćAplikacja(){
powrót<Lada />
}

Licznik będzie działał dokładnie tak samo, jak wcześniej, ale dużą różnicą jest to, że wszystkie twoje stany znajdują się lokalnie w tym Lada część. Więc jeśli potrzebujesz mieć inny licznik na stronie głównej, będziesz mieć dwa niezależne liczniki. Każdy licznik jest samowystarczalny i dba o cały swój własny stan.

Obsługa stanu w bardziej złożonych aplikacjach

Inną sytuacją, w której można użyć stanu globalnego, są formularze. The Aplikacja Poniższy komponent przekazuje dane formularza (adres e-mail i hasło) oraz metodę ustawiającą do Forma loginu część.

import { stan użycia } z"reagować";
import { Forma loginu } z"./Forma loginu";

funkcjonowaćAplikacja() {
konst [formData, setFormData] = useState({
e-mail: "",
hasło: "",
});

funkcjonowaćzaktualizuj dane formularza(nowe dane) {
setFormData((poprzedni) => {
powrót { ...poprzednie, ...noweDane};
});
}

funkcjonowaćw dniu Prześlij() {
konsola.log (dane formularza);
}

powrót (
dane={formularzDane}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

The Forma loginu składnik pobiera dane logowania i renderuje je. Po przesłaniu formularza wywołuje on Uaktualnij dane funkcja, która jest również przekazywana z komponentu nadrzędnego.

funkcjonowaćForma loginu({ onSubmit, dane, aktualizacja danych}) {
funkcjonowaćuchwytPrześlij(mi) {
e.preventDefault();
onPrześlij();
}

powrót (


Zamiast zarządzać stanem komponentu nadrzędnego, lepiej przenieść stan do LoginForm.js, gdzie użyjesz kodu. Dzięki temu każdy komponent jest samowystarczalny i nie jest zależny od innego komponentu (tj. Rodzica) w zakresie danych. Oto zmodyfikowana wersja tzw Forma loginu:

import { useRef } z"reagować";

funkcjonowaćForma loginu({ onPrześlij}) {
konst emailRef = useRef();
konst hasłoRef = useRef();

funkcjonowaćuchwytPrześlij(mi) {
e.preventDefault();
onPrześlij({
e-mail: e-mailRef.bieżąca.wartość,
hasło: hasłoRef.aktualna.wartość,
});
}

powrót (


Tutaj wiążesz dane wejściowe ze zmienną za pomocą ref atrybuty i użyjRef React hook, zamiast bezpośrednio przekazywać metody aktualizacji. Pomaga to usunąć pełny kod i zoptymalizuj wydajność formularza za pomocą haka useRef.

W komponencie nadrzędnym (Aplikacja.js), możesz usunąć zarówno stan globalny, jak i updateFormData() metodę, ponieważ już jej nie potrzebujesz. Pozostała tylko funkcja onPrześlij(), które wywołujesz z wnętrza Forma loginu komponent do rejestrowania danych logowania na konsoli.

funkcjonowaćAplikacja() {
funkcjonowaćw dniu Prześlij(tworzyć dane) {
konsola.log (dane formularza);
}

powrót (
dane={formularzDane}
updateData={updateFormData}
onSubmit={onSubmit}
/>
);
}

Nie tylko uczyniłeś swój stan tak lokalnym, jak to tylko możliwe, ale faktycznie wyeliminowałeś potrzebę posiadania jakiegokolwiek stanu (i użyłeś go ref Zamiast). Więc twój Aplikacja komponent stał się znacznie prostszy (mając tylko jedną funkcję).

Twój Forma loginu komponent również stał się prostszy, ponieważ nie trzeba było martwić się aktualizacją stanu. Raczej śledzisz tylko dwa ref, i to wszystko.

Obsługa stanu współdzielonego

Jest jeden problem z podejściem polegającym na próbie uczynienia państwa tak lokalnym, jak to tylko możliwe. Często napotykasz scenariusze, w których składnik nadrzędny nie używa stanu, ale przekazuje go do wielu składników.

Przykładem jest posiadanie a TodoKontener komponent nadrzędny z dwoma komponentami podrzędnymi: Lista rzeczy do zrobienia I Do zrobienia.

funkcjonowaćTodoKontener() {
konst [todos, setTodos] = useState([])

powrót (
<>


</>
)
}

Oba te komponenty potomne wymagają todos stan, tak TodoKontener przekazuje je obojgu. W takich scenariuszach musisz sprawić, by stan był jak najbardziej lokalny. W powyższym przykładzie umieszczenie go w pliku TodosContainer jest tak lokalny, jak to tylko możliwe.

Gdybyś umieścił ten stan w swoim Aplikacja komponent, nie byłby tak lokalny, jak to tylko możliwe, ponieważ nie jest najbliższym rodzicem dwóch komponentów, które potrzebują danych.

W przypadku dużych aplikacji zarządzanie stanem tylko za pomocą useState() hak może okazać się trudny. W takich przypadkach może być konieczne wybranie opcji Interfejs API kontekstu reakcji Lub Zareaguj Redux skutecznie zarządzać państwem.

Dowiedz się więcej o hakach reagowania

Haki stanowią podstawę React. Używając haków w React, możesz uniknąć pisania długiego kodu, który w przeciwnym razie używałby klas. Haczyk useState() jest bezsprzecznie najczęściej używanym hakiem Reacta, ale istnieje wiele innych, takich jak useEffect(), useRef() i useContext().

Jeśli chcesz stać się biegły w tworzeniu aplikacji w React, musisz wiedzieć, jak używać tych haków w swojej aplikacji.