Lekcja #7: Wewnętrzny stan komponentu

Darmowy podgląd
Najpierw trzeba Zadania #4: Kontrola typów obiektu props przed oglądania tej lekcji

Każdy komponent React będący klasą dziedziczącą z React.Component może posiadać swój własny, wewnętrzny stan. Na stanie komponentu opierają się wszystkie interakcje z interfejsem użytkownika oraz wszystkie dynamiczne zmiany wyglądu danego komponentu.

Wiąże się to z cyklem życia komponentu, o którym więcej dowiesz się z kolejnej lekcji. Na tę chwilę musimy jedynie wiedzieć, że każda zmiana stanu komponentu powoduje ponowne wywołanie metody render (oraz metod render wszystkich komponentów dzieci, jeśli takie istnieją).

Deklaracja początkowego stanu komponentu

Deklaracji stanu komponentu oraz definicji jego początkowych wartości zawsze dokonujemy w konstruktorze klasy komponentu:

Uwaga! Zwróć uwagę na pierwszą linię konstruktora czyli wywołanie super(props) – dobrą praktyką jest, aby zawsze wywoływać konstruktor bazowy przekazując mu obiekt props! Wtedy, jeśli będziesz miał potrzebę odwołania się do tego obiektu, możesz zrobić to poprzez this.props, czyli tak jak w pozostałych miejscach w komponencie (jeśli tego nie zrobisz, this.props zwróci wartość „undefined”). W przeciwnym razie jedynym sposobem dostępu do obiektu props w konstruktorze jest parametr wywołania konstruktora.

Wróćmy jednak do deklaracji stanu początkowego komponentu. Jak widać w przykładzie, aby zadeklarować stan komponentu wystarczy do właściwości this.state przypisać obiekt. Wartości przypisane do poszczególnych właściwości tego obiektu stanowią stan początkowy komponentu.

Praca ze stanem komponentu

Stan komponentu wykorzystuje się w podobny sposób jak wartości przekazane do komponentu, które dostępne są poprzez obiekt props. Mając stan komponentu, zdefiniowany tak jak w powyższym przykładzie, możemy łatwo wyświetlić jego wartości w metodzie render:

Powyższy przykład implementacji metody render pokazuje, że do poszczególnych wartości stanu można się dostać po prostu poprzez this.state. Czyli tak jak już wspomniałem: analogicznie do this.props.

Przekazywanie stanu do zagnieżdżonych komponentów

Jeśli dany komponent renderuje inne, zagnieżdżone komponenty, to możemy im przekazać stan komponentu rodzica. Robimy to za pomocą atrybutów, tak jak w każdym innym przypadku:

W powyższym przykładzie do komponentu UserData przekazujemy wartości stanu text oraz age przypisując je odpowiednio do atrybutów name oraz age komponentu. Wewnątrz komponentu UserData dane te dostępne są już poprzez obiekt props:

Zmiana stanu komponentu

Do zmiany stanu komponentu służy specjalna metoda this.setState dziedziczona z klasy React.Component:

W przykładzie wykorzystano zdarzenie onClick oraz funkcję „inline” obsługi zdarzenia – więcej na ten temat dowiesz się w dalszej części kursu. Na razie wystarczy jeśli napiszę, że powyższy kod wywołuje metodę this.setState w momencie naciśnięcia guzika przez użytkownika. Skupmy się jednak na innej rzeczy – metodzie this.setState, która powoduje zmianę stanu komponentu.

Jak widzisz, aby zmienić wartość stanu counter, do funkcji this.setState przekazano obiekt, zawierający właściwość o tej samej nazwie, do której przypisano nową wartość stanu (w przykładzie jest to poprzednia wartość zwiększona o jeden). Co ważne, jeśli w this.state zdefiniowano więcej właściwości, nie oznacza to, że musimy wszystkie je powtarzać podczas wywołania metody this.setState. Wystarczy przekazać obiekt zawierający tylko te właściwości, które faktycznie chcemy zmienić.

Uwaga! Każde wywołanie metody this.setState powoduje ponowne wywołanie metody render komponentu (oraz metod render komponentów zagnieżdżonych). Jest to zachowanie pożądane, ponieważ pozwala odwzorować zmiany stanu na ekranie (więcej o tym w kolejnej lekcji). Z tego powodu, stan należy zmieniać tylko i wyłącznie za pomocą metody this.setState! Każda inna próba zmiany stanu, na przykład poprzez bezpośrednie przypisanie nowej wartości do właściwości stanu (na przykład: this.state.text = "hello") nie będzie skutkować ponownym renderowaniem (czyli nic się nie zmieni na widoku)!

Funkcja zmieniająca stan

Zanim przejdziemy dalej, warto wspomnieć o potencjalnych niebezpieczeństwach związanych z metodą this.setState.

Z powodów wydajnościowych, operacja zmiany stanu może zostać przez React wykonana asynchronicznie i nie mamy na to wpływu. Z tego powodu nowa wartość stanu, która opiera się o aktualną jego wartość (tak, kod ostatniego przykładu nie jest idealny…), może to być potencjalnie niebezpieczne:

W powyższym kodzie wartość this.state.text może nie być jeszcze zaktualizowana poprzednią (albo być już zaktualizowana następną) zmianą, więc nie powinno się tego robić w powyższy sposób.

Jako że do komponentu, za pomocą atrybutów, może być przekazana wartość stanu innego komponentu, to tak samo nie należy przy zmianie stanu opierać się na aktualnych wartościach obiektu props:

Powyższy kod również jest potencjalnie niebezpieczny!

Na szczęście nie jesteśmy pozostawieni sami sobie z tym problemem! Metoda this.setState, oprócz obiektu, może przyjmować również funkcję wywołania zwrotnego (ang. callback)… Spójrz na przykład:

W powyższym przykładzie skorzystaliśmy z parametru prevState, który, jak sama nazwa wskazuje, zawiera (napewno) poprzedni stan komponentu. Jest więc bezpiecznie oprzeć się na nim przy definiowaniu nowego stanu.

Jak widzisz, funkcja ta przyjmuje również obiekt props, możemy więc łatwo z niego skorzystać:

W ten sposób mamy pewność, że korzystamy z właściwej wartości obiektu props.

Powrót do:Podstawy React – kurs on-line