useRef() похож на useSate(), поскольку он позволяет нам сохранять (оставлять неизменными) значения между рендерингами, но, в отличие от useState(), хук Ref
не вызывает повторный рендеринг, когда изменяемое значение изменено.
useRef() возвращает изменяемый объект, текущее свойство которого установлено с начальным значением, которое передается в качестве аргумента функции Ref.
const refObject = useRef(initial_value);
В приведенном выше примере refObject
— это возвращаемый объект. Этот объект имеет свойство current
, которое можно использовать для получения значения объекта, на который ссылаются, в любое время.
Есть два основных варианта использования useRef():
- Чтобы создать постоянные изменяемые переменные (они называются ссылками или ссылками).
- Чтобы получить доступ к элементам DOM (или элементам React).
Давайте углубимся в это.
1. useRef() для создания постоянных изменяемых переменных.
Попытка подсчитать количество повторных рендеров компонента с использованием useState приведет к бесконечному циклу, поскольку сам useState вызывает повторный рендеринг. Это продемонстрировано в примере ниже.
import React,{useState, useEffect} from 'react' function App() { const [text, setText] = useState('') const [count, setCount] = useState(0) useEffect(() => { setCount(prevStateCount => prevStateCount + 1) }) return ( <div> <input value={text} onChange={e=>setText(e.target.value)} /> <div>Type some text in the box</div> <div>Component rendered {count} times</div> </div> ) } export default App
Во время начального рендеринга компонента «счетчик» увеличивается, что приводит к повторному рендерингу компонента, и, следовательно, счетчик снова увеличивается, что приводит к повторному рендерингу компонента. По сути, это бесконечный цикл увеличения «счетчика» и повторного рендеринга компонентов.
Рефы в помощь 🛟…
Рефы можно использовать для решения проблемы с бесконечным циклом, возникающей из-за повторного рендеринга при использовании хука состояния.
import React,{useState, useEffect, useRef} from 'react' function App() { const [text, setText] = useState('') const count = useRef(1) useEffect(() => { count.current = count.current + 1 }) return ( <div> <input value={text} onChange={e=>setText(e.target.value)} /> <div>Type some text in the box</div> <div>Component rendered {count.current} times</div> </div> ) } export default App
useRef() заменяет useState(), а count
— это объект со свойством current
. Свойство current
сохраняется при обновлении между различными рендерингами.
На изображении ниже мы можем наблюдать, что каждый раз, когда в поле ввода вводится символ, счетчик увеличивается. Поскольку введено слово «яблоко», счетчик увеличивается 6 раз (1 при начальном рендеринге + увеличение на 1 для каждого символа). Независимо от того, сколько раз изменяется счетчик, наш компонент не подвергается повторному рендерингу, поскольку он отделен от цикла рендеринга нашего компонента.
2. Доступ к элементам DOM
Более распространенное использование ссылок — это когда нам нужно ссылаться на элементы HTML.
Каждый элемент HTML имеет атрибут ref
. Мы можем добавить атрибут ref
к элементу, чтобы получить доступ к элементу непосредственно в DOM.
Давайте разберем этот вариант использования на примере. Рассмотрим код для сценария, в котором мы хотим сосредоточиться на вводе при нажатии кнопки.
import React,{useRef} from 'react' function App() { const inputRef = useRef() const focus = () => { inputRef.current.focus() } return ( <div> <input ref={inputRef} /> <button onClick={focus}>Click to focus</button> </div> ) } export default App
Каждый раз, когда inputRef отображается на экране, переменная inputRef устанавливается в элемент input
. Поэтому в функции focus
мы обращаемся к текущему свойству переменной inputRef (это соответствует элементу input
), а затем фокусируемся на нем.
На скриншоте, прикрепленном ниже, мы можем наблюдать, как нажатие на кнопку фокусируется на вводе.
Еще один лайфхак с useRef() 💡 →
Представьте себе обновление состояния для каждого символа при работе с формами. Это может быть немного чрезмерным. Используя Refs, мы можем установить соединение между HTML-элементом, который в конечном итоге отображается, и другим кодом JavaScript.
👏 Поздравляем и отличного настроения 👏. Вы рассмотрели три хука React. Это было бы хорошим моментом, чтобы заново собрать свое понимание этих крючков.
Если вы чувствуете себя уверенно 😎, погрузитесь прямо в useReducer().