Małe przypomnienie useState. Lekcja krótka i szybka, do dzieła.

Ok, łatwy przykład:

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

Swoją drogą można było zastosować updater function, który już poznaliśmy. A oto hook useCount:

import { useState } from 'react';

function useCount(initialCount = 0) {
  const [count, setCount] = useState(initialCount);

  const increment = () => {
    setCount(count + 1);
  };

  const decrement = () => {
    setCount(count - 1);
  };

  const reset = () => {
    setCount(initialCount);
  };

  return {
    count,
    increment,
    decrement,
    reset,
  };
}

export default useCount;

Też brakuje mi updater function. Bo to nie chodzi o to, że decrement czy increment są strzałkowe – tu chodzi o to, że setState może albo działać na state (i state jest zależnością), albo przyjąć callback, którego argument to prevState (jaki by on nie był) a return to instrukcja, co z tym prevState zrobić:

function handleClick() {
  setAge(a => a + 1); // setAge(42 => 43)
  setAge(a => a + 1); // setAge(43 => 44)
  setAge(a => a + 1); // setAge(44 => 45)
}

Ok, następny przykład useState:

import { useState } from 'react';

export default function MyInput() {
  const [text, setText] = useState('hello');

  function handleChange(e) {
    setText(e.target.value);
  }

  return (
    <>
      <input value={text} onChange={handleChange} />
      <p>You typed: {text}</p>
      <button onClick={() => setText('hello')}>
        Reset
      </button>
    </>
  );
}

Tu mamy onClick setText z argumentem, żeby to działało – onclick musi być przekazany jako funkcja strzałkowa zwracająca wywołanie funkcji setText.

Warto zwrócić uwagę:

  • Zmienne reaktywne state zawsze lądują w tablicy zależności
  • Funkcje setState nigdy nie lądują w tablicy zależności
  • Aby wywołać setState bez używania state (i produkowania zależności) musimy:
    • Skorzystać z updater function, która w callbacku ma prevState i w returnie pokazane, co z nim zrobić
    • Wpisać tam jakąś wartość, np. setState(42) nie powoduje żadnych zależności, setState(get42()) tylko funkcji get42, której jeszcze można zrobić useCallback i tam określić zależności

Wartości boolowskie się świetnie nadają na stan:

import { useState } from 'react';

export default function MyCheckbox() {
  const [liked, setLiked] = useState(true);

  function handleChange(e) {
    setLiked(e.target.checked);
  }

  return (
    <>
      <label>
        <input
          type="checkbox"
          checked={liked}
          onChange={handleChange}
        />
        I liked this
      </label>
      <p>You {liked ? 'liked' : 'did not like'} this.</p>
    </>
  );
}

Czemu świetnie? Bo zawsze, jak chcemy im toggle zrobić to w setState dajemy updater z prevState => !prevState.

Tutaj taki hook z internetu, useToggle:

import { useState } from "react"

export default function useToggle(defaultValue) {
  const [value, setValue] = useState(defaultValue)

  function toggleValue(value) {
    setValue(currentValue =>
      typeof value === "boolean" ? value : !currentValue
    )
  }

  return [value, toggleValue]
}

Więcej Reacta niedługo…