Хук useRef для работы с рефами в React

На этом уроке мы поработаем с рефами. Для наглядности давайте разберем работу хука useRef в сравнении с хуком useState.

Давайте создадим компонент с кнопкой:

return ( <div> <button> state click </button> </div> );

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

import { useState } from 'react';

И заведем стейт state:

const [state, setState] = useState(0);

А сейчас сделаем так, чтобы по клику на кнопку наш state увеличивался бы на 1. Значение стейта будем выводить прямо в тексте кнопки:

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

Опишем функцию для обработки клика по кнопке handleStateClick:

function handleStateClick() { setState(state + 1); }

Понажимаем кнопочку и увидим, как растет значение стейта.

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

Для начала, импортируем в компонент useRef:

import { useRef } from 'react';

И заведем реф ref. Своим результатом хук useRef возвращает объект рефа с единственным свойством current, которое нас и будет интересовать в дальнейшем. Установим его начальное значение в 0:

const ref = useRef(0);

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

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

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

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

Теперь понажимаем нашу кнопку. И что же мы видим? При клике по ней, как у нас был изначально 0, так он и не меняется.

Вы, конечно, можете начать сомневаться в том, что значение вообще меняется. Давайте это проверим. Для этого в функции обработчика клика добавим еще строчку кода с выводом значения current в консоль:

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

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

Теперь мы видим, что в отличие от стейта, изменение значения рефа не вызывает рендеринг компонента. Поэтому мы каждый раз в тексте кнопки видим начальное значение 0.

Таким образом, если ваши данные используются для рендеринга, то храните их в стейте, а если вам не нужен рендеринг, в таком случае использование рефов может стать более эффективным.

Пусть в вашем компоненте есть абзац с текстом 'text' и кнопка. Сделайте так, чтобы каждый раз по клику на кнопку в конец текста абзаца добавлялся восклицательный знак. Сделайте это с помощью стейта.

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



Чат с GPT Компилятор