Хук useRef за работа с рефове в React

В този урок ще работим с рефове. За по-голяма яснота нека разгледаме работата на хука useRef в сравнение с хука useState.

Нека създадем компонент с бутон:

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

Импортираме в компонента useState:

App.jsximport { useState } from 'react';

И ще създадем състояние state:

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

А сега нека направим така, че при клик върху бутона нашето state да се увеличава с 1. Стойността на състоянието ще извеждаме директно в текста на бутона:

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

Ще опишем функцията за обработка на клик върху бутона handleStateClick:

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

Ще натиснем бутона няколко пъти и ще видим как нараства стойността на състоянието.

А сега нека създадем компонент App, но използвайки не състояние, а реф.

Първо, импортираме в компонента useRef:

App.jsximport { useRef } from 'react';

И ще създадем реф ref. Резултатът от хука useRef връща обект на рефа с единствено свойство current, което ще ни бъде интересно в последствие. Ще зададем началната му стойност на 0:

App.jsxconst ref = useRef(0);

Ще сложим обработчик на бутона за клик. Помнете, че трябва да четем/променяме не самия ref, а неговото свойство current:

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

Добавяме функция за обработка на клик върху нашия бутон. Тук ще увеличаваме current с 1, както в предишния пример със състояние. За разлика от състоянието, където се изисква функция setState за промяна на стойността му, със свойството на рефа работим директно:

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

Сега ще натиснем нашия бутон. И какво виждаме? При клик върху него, както беше първоначално 0, така си остава и не се променя.

Разбира се, може да започнете да се съмнявате в това, че стойността изобщо се променя. Нека проверим това. За целта във функцията на обработчика на клик добавяме още един ред код за извеждане на стойността на current в конзолата:

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

А сега, отворили конзолата в браузъра, отново щe натиснем бутона и ще се убедим, че стойността наистина се променя при всяко натискане и няма измама.

Сега виждаме, че за разлика от състоянието, промяната на стойността на рефа не предизвиква рендериране на компонента. Затова всеки път в текста на бутона виждаме началната стойност 0.

По този начин, ако вашите данни се използват за рендериране, то ги съхранявайте в състояние, а ако не ви трябва рендериране, в такъв случай използването на рефове може да се окаже по-ефективно.

Задание 1

Нека във вашия компонент има параграф с текст 'text' и бутон. Направете така, че всеки път при клик на бутона в края на текста на параграфа да се добавя удивителен знак. Направете това със състояние.

Задание 2

Създайте компонент App, но вместо състояние сега използвайте реф. Уверете се, че при натискане на бутона текстът на параграфа няма да се променя. Добавете също извеждане на текста на параграфа в конзолата, отворете я и се уверете, че всъщност текстът се променя.