Najbardziej podstawowym hookiem jest useState(). Umożliwia on zarządzanie wartością stanu pomiędzy kolejnymi wywołaniami funkcji komponentu.
useState() zwraca tablicę z dwiema wartościami: stanem i funkcją do jego aktualizacji. Zgodnie z konwencją nazwa funkcji do aktualizacji powinna zaczynać się od czasownika set, czyli ustawiać. Jeśli zmienną stanu nazwiemy user to funcja powinna nazywać się setUser.
const [state, setState] = useState();
useState() przyjmuje jako parametr początkową wartość stanu
const [state, setState] = useState(4);
console.log(state); // 4
console.log(state); // 4
Funkcja setState przyjmuje jako parametr nową wartość stanu lub callback
const [state, setState] = useState(4);
console.log(state); // 4
setState(24);
console.log(state); // 24
console.log(state); // 4
setState(24);
console.log(state); // 24
Callback przyjmuje jako parametr aktualna wartość lub referencję stanu:
const [state, setState] = useState(4);
console.log(state); // 4
setState(state => state + 1);
console.log(state); // 5
console.log(state); // 4
setState(state => state + 1);
console.log(state); // 5
Po co setState przyjmuje callback jako parametr? Po to, żeby w każdym przypadku, gdy nasz kod nie ma dostępu do aktualnego state móc jednak z niego korzystać. Dość toporny przykład pokazujący jak to działa jest z wykorzystaniem setInterval
.
import React from "react";
export default function App() {
const [state, setState] = React.useState(0);
function updateState() {
setState((state || 0) + 1);
}
React.useEffect(() => {
const interval = setInterval(updateState, 3000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
{console.log("rerender", state)}
<h3>{state}</h3>
</div>
);
}
export default function App() {
const [state, setState] = React.useState(0);
function updateState() {
setState((state || 0) + 1);
}
React.useEffect(() => {
const interval = setInterval(updateState, 3000);
return () => clearInterval(interval);
}, []);
return (
<div className="App">
{console.log("rerender", state)}
<h3>{state}</h3>
</div>
);
}
Powyższy przykład pokazuje ustawianie nowej wartości stanu co 3 sekundy. Niestety, stan ustawia się na 1, cały czas co 3 sekundy, ponieważ funkcja updateState jest utworzona, gdy state wynosi 0. I tak zostaje przekazana do setInterval. Co 3 sekundy setInterval zwieksza state równy 0 o 1...
zobacz na Sandbox
Sposobem na naprawienie (poza zabawą scope i clojure) jest użycie callbacku jako parametru w setState, wtedy cała funkcja bedzie wygladać tak:
zobacz na Sandbox
function updateState() {
setState(state => (state || 0) + 1);
}
setState(state => (state || 0) + 1);
}
state przekazywany do callbacku jest tym aktualnym, wiec co 3 sekundy rośnie jego wartośc o 1.
Brak komentarzy:
Prześlij komentarz