Hook useRef do pracy z referencjami w React

W tej lekcji popracujemy z referencjami. Dla przejrzystości przeanalizujmy działanie hooka useRef w porównaniu z hookiem useState.

Stwórzmy komponent z przyciskiem:

App.jsxreturn (
  <div>
    <button>
      state click
    </button>
  </div>
);

Zaimportujmy do komponentu useState:

App.jsximport { useState } from 'react';

I utwórzmy stan state:

App.jsxconst [state, setState] = useState(0);

A teraz zróbmy tak, aby po kliknięciu przycisku nasz state zwiększał się o 1. Wartość stanu będziemy wyświetlać bezpośrednio w tekście przycisku:

App.jsx<button onClick={handleStateClick}>
  state click: {state}
</button>

Opiszmy funkcję obsługi kliknięcia przycisku handleStateClick:

App.jsxfunction handleStateClick() {
  setState(state + 1);
}

Po kliknięciu przycisku zobaczymy, jak rośnie wartość stanu.

A teraz stwórzmy komponent App, ale używając nie stanu, a referencji.

Na początek zaimportujmy do komponentu useRef:

App.jsximport { useRef } from 'react';

I utwórzmy referencję ref. Hook useRef zwraca w wyniku obiekt referencji z jedyną właściwością current, która będzie nas interesować w dalszej części. Ustawmy jego początkową wartość na 0:

App.jsxconst ref = useRef(0);

Nałóżmy na przycisk procedurę obsługi kliknięcia. Pamiętajmy, że powinniśmy czytać/zmieniać nie sam ref, a jego właściwość current:

App.jsx<button onClick={handleRefClick}>
  ref click: {ref.current}
</button>

Dodajmy funkcję obsługi kliknięcia naszego przycisku. Tutaj będziemy zwiększać current o 1, tak jak w poprzednim przykładzie ze stanem. W przeciwieństwie do stanu, gdzie wymagana jest funkcja setState do zmiany jego wartości, ze właściwością referencji pracujemy bezpośrednio:

App.jsxfunction handleRefClick() {
  ref.current = ref.current + 1;
}

Teraz kliknijmy nasz przycisk. I co widzimy? Po kliknięciu na niego, jak mieliśmy początkowo 0, tak się nie zmienia.

Możecie oczywiście zacząć wątpić w to, że wartość w ogóle się zmienia. Sprawdźmy to. W tym celu w funkcji obsługi kliknięcia dodajmy jeszcze linijkę kodu z wypisaniem wartości current do konsoli:

App.jsxfunction handleRefClick() {
  ref.current = ref.current + 1;
  console.log('ref click: ' + ref.current);
}

A teraz, otwierając konsolę w przeglądarce, ponownie kliknijmy przycisk i przekonajmy się, że wartość rzeczywiście zmienia się przy każdym kliknięciu i nie ma żadnego oszustwa.

Teraz widzimy, że w przeciwieństwie do stanu, zmiana wartości referencji nie powoduje renderowania komponentu. Dlatego za każdym razem w tekście przycisku widzimy początkową wartość 0.

Zatem, jeśli twoje dane są używane do renderowania, to przechowuj je w stanie, a jeśli nie potrzebujesz renderowania, w takim przypadku użycie referencji może być bardziej efektywne.

Задание 1

Niech w twoim komponencie będzie akapit z tekstem 'text' i przycisk. Zrób tak, aby za każdym razem po kliknięciu przycisku na koniec tekstu akapitu dodawał się wykrzyknik. Zrób to za pomocą stanu.

Задание 2

Stwórz komponent App, ale zamiast stanu teraz użyj referencji. Upewnij się, że przy naciśnięciu przycisku tekst akapitu nie będzie się zmieniać. Dodaj także wypisanie tekstu akapitu do konsoli, otwórz ją i upewnij się, że w rzeczywistości tekst się zmienia.