Zacznijmy może od wykonania ćwiczenia z poprzedniego wpisu. Zadanie brzmiało tak:
Dodaj dwa nowe liczniki. Pierwszy, który będzie zliczał wszystkie kliknięcia w przyciski (tzn. kliknięcie w+
i-
daje 0 na obecnym liczniku oraz 2 na nowym liczniku), oraz drugi, który będzie zliczał podwójne kliknięcia (tzw. double click) na elemencie z wynikiem.
Wydaje się proste, ale implementacja odkrywa przez Tobą pewien ważny szczegół dotyczący działania funkcji setState
. W jaki sposób chcielibyśmy tutaj aktualizować stan? Musimy przechowywać jeden licznik z sumą, drugi zliczający łączne kliknięcia oraz trzeci, który będzie przechowywał podwójne kliknięcia. To co jest tutaj istotne to fakt, że w momencie pojedynczego kliknięcia aktualizujesz tylko dwa liczniki, a trzeci pozostaje bez zmian. Jak to najprościej zaimplementować?
Jak działa setState
?
increment() {
this.setState({
sumCount: this.state.counter + 1
totalCount: this.state.totalCount + 1
doubleClickCount: this.state.dblClickCount
})
}
Działa, po prostu do doubleClickCount
zawsze przypisana zostaje niezmieniona wartość this.state.doubleClickCount
. Ale czy to konieczne? Co by było, gdyby stan komponentu składał się nie z 3, a z 15 pól? Nie dyskutujmy teraz czy to dobre rozwiązanie, tylko zastanów się jak by musiała wyglądać każda aktualizacja stanu… właśnie.
Na szczęście setState
jest mądrzejsze i automatycznie łączy obecny stan z tym podanym mu jako argument — i nadpisuje tylko podane własności. To co się nie zmienia pomijasz:
increment() {
this.setState({ // doubleClickCount pozostanie niezmienne
sumCount: this.state.counter + 1
totalCount: this.state.totalCount + 1
})
}
A tutaj w pełni działające rozwiązanie:
Jeśli to nie jest dla Ciebie jasne, nie ma w tym nic złego :) Możesz zadać nam pytanie w komentarzu! zapisz się na szkolenie z React.
Funkcja przekazana do setState
Widzisz, że do setState
możemy po prostu przekazać obiekt, który zostanie połączony z obecnym stanem i nadpisze podane własności. I to, do niedawna, była jedyna opcja. Od Reacta 16 polecanym sposobem aktualizowania stanu jest przekazanie do setState
funkcji, a nie obiektu. Taka funkcja to tzw. updater. Jak to działa? Updater to taka funkcja, która jako argument przyjmuje obecny stan i jako wynik zwraca obiekt, który zostanie połączony z istniejącym stanem. Przykładowo dla nas:
increment() {
this.setState(prevState => {
return {
sumCount: prevState.sumCount + 1,
totalCount: prevState.totalCount + 1
};
});
}
Jakie są zalety tego rozwiązania względem po prostu przekazania obiektu do setState
? W tym przypadku żadne. setState
jest asynchroniczne (o tym zaraz) i sprawia problemy, gdy wywołamy je kilka razy pod rząd — tutaj pomoże nam updater. Dodatkowo, updater pomaga poprawić wydajność aplikacji — jeśli w updaterze zwrócisz null
to nie zostanie wykonany ponowny render. Poświęcę temu wszystkiemu inny wpis!
setState
i callback
Dokładnie tak jak w nagłówku. Co to oznacza? Najprościej mówiąc, że wywołanie setState
nie zmienia stanu od razu, tylko dopiero po jakimś czasie. Czyli, przykładowo, próba odczytania stanu od razu po jego zmianie przez setState
pokaże nam nadal stary, nieaktualny stan. Otwórz konsolę i kliknij w przycisk w tym przykładzie:
Jak naprawić ten problem? Otóż setState
przyjmuje też drugi argument: callback. Jeśli jako drugi argument przekażesz funkcję to zostanie ona wywołana w momencie, gdy stan będzie już zaktualizowany. Spójrz po prostu na przykład (z widoczną konsolą):
Jeśli chcesz na bieżąco dowiadywać się o kolejnych częściach kursu React.js to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.
Ćwiczenie
Ćwiczenie: Napisz komponent, który będzie miał dwa inputy na imię i nazwisko. Obok, powinien się wyświetlać tekst wpisany w te pola (imię nazwisko). Użyj do tego atrybutu onInput
oraz funkcji setState
.
Napisz w komentarzu jak Ci się podoba obsługa formularzy w React. Poświęcę temu jeden z kolejnych odcinków, więc chcę wiedzieć już teraz jakie masz uwagi :)