Aby aplikacja mogła dynamicznie reagować na interakcje użytkownika, musi aktualizować swój widok w oparciu o dane, które mogą się zmieniać w czasie. React realizuje to za pomocą mechanizmu znanego jako Stan (State), który pozwala aplikacji na aktualizację bez konieczności jej przeładowania (https://react.dev/learn/state-a-components-memory).
React hooks
Hooki to specjalne funkcje w React, używane wyłącznie w komponentach. Wprowadzają one dodatkowe mechanizmy do aplikacji. Wszystkie hooki rozpoczynają się od słowa use
, a pełny ich spis dostępny jest w dokumentacji React.
useState
Funkcja useState
dostarcza mechanizm stanu. Wywołując tę funkcję, tworzymy zmienną stanu, którą React „śledzi”.
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Liczba kliknięć: {count}</p>
<button onClick={() => setCount(count + 1)}>
Kliknij mnie
</button>
</div>
);
}
Podczas wywoływania useState
, określamy wartość początkową, a w rezultacie otrzymujemy dwuelementową tablicę. Pierwszy element tej tablicy to aktualna wartość zmiennej, a drugi to funkcja służąca do aktualizacji tej zmiennej.
Proces aktualizacji stanu:
Po każdej aktualizacji stanu, React ponownie wykonuje komponent funkcyjny, w którym został wywołany useState
, oraz wszystkie jego komponenty potomne. Podczas tej aktualizacji React wylicza wszystkie wartości na nowo, aktualizuje Virtual DOM i sprawdza, czy potrzebna jest aktualizacja Real DOM.
Nazewnictwo
useState
zwraca tablicę z dwoma wartościami:
- Pierwszy element to aktualna wartość stanu. Nazwa powinna opisywać, co przechowuje stan; unikaj ogólnych nazw, takich jak
value
czyx
. - Drugi element to funkcja aktualizująca stan; zazwyczaj dodaje się przedrostek
set
do nazwy pierwszego elementu, np.setEmail
,setUserName
.
Typy danych
Funkcja useState
akceptuje jeden argument, który może być dowolnego typu dostępnego w JavaScript, zarówno prostego (takiego jak Number, String, czy Boolean), jak i referencyjnego (np. obiekty czy tablice). Ważne jest, aby pamiętać, że przy aktualizacji stanu należy podać pełną nową wartość – nawet jeśli w obiekcie zmieni się tylko jeden atrybut, konieczne jest podanie całego obiektu, aby uniknąć nadpisania.
Przykład gdzie nadpiszemy obiekt:
import React, { useState } from 'react';
function UserProfile() {
const [user, setUser] = useState({ name: 'Jan', surname: 'Kowalski' });
const updateName = () => {
setUser({ name: 'Adam' });
};
return (
<div>
<p>Imię: {user.name}</p>
<p>Nazwisko: {user.surname}</p>
<button onClick={updateName}>Zmień imię na Adam</button>
</div>
);
}
Poprawny sposób aktualizacji obiektu:
import React, { useState } from 'react';
function UserProfile() {
const [user, setUser] = useState({ name: 'Jan', surname: 'Kowalski' });
const updateName = () => {
setUser(prevUser => ({ ...prevUser, name: 'Adam' }));
};
const updateSurname = () => {
setUser(prevUser => ({ ...prevUser, surname: 'Nowak' }));
};
return (
<div>
<p>Imię: {user.name}</p>
<p>Nazwisko: {user.surname}</p>
<button onClick={updateName}>Zmień imię na Adam</button>
<button onClick={updateSurname}>Zmień nazwisko na Nowak</button>
</div>
);
}
Wiązanie dwukierunkowe – two-way binding
Wiązanie dwukierunkowe to technika w programowaniu interfejsów użytkownika, która synchronizuje stan elementu interfejsu (np. pola formularza) z modelem danych (stanem komponentu). Umożliwia to, aby zmiany w jednym miejscu (interfejsie użytkownika lub stanie) były automatycznie odzwierciedlane w drugim, zapewniając spójność i interaktywność.
import React, { useState } from 'react';
export default function SimpleInput() {
const [inputValue, setInputValue] = useState('');
const handleInputChange = (e) => {
setInputValue(e.target.value);
};
return (
<div>
<input
type="text"
value={inputValue}
onChange={handleInputChange}
/>
</div>
);
}