poniedziałek, 19 października 2020

react hooks - useState

Hooki w react pojawiły się pod koniec 2018 roku. Umożliwjają one wygodne pisanie komponentów funkcyjnych, dzielenie odpowiedzialności w kodzie oraz tworzenie małych plików - łatwych w testowaniu, utrzymaniu i wygodnych, gdy trzeba znaleźć błąd.

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

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

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

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>
  );
}

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);
  }

state przekazywany do callbacku jest tym aktualnym, wiec co 3 sekundy rośnie jego wartośc o 1.

Brak komentarzy:

Prześlij komentarz