Коротка відповідь
middlecreateRef — це класовий API, що створює нову reference‑об’єкт при кожному рендері; useRef — це хук, що повертає стабільну reference‑об’єкт між рендерами. Обидва використовуються для доступу до DOM‑елементів, але useRef дозволяє зберігати мутабельне значення без повторного створення. При класах застосовують this.myRef = createRef(), а у функціональних компонентах useRef() виводить { current: null } і зберігається між рендерами.
Повне пояснення
Що це і навіщо
createRef– API для класових компонентів, що повертає новий об’єкт reference ({ current: null }) кожного разу, коли компонент створюється.useRef– хук для функціональних компонентів, що повертає той самий reference‑об’єкт між рендерами.
Ключові принципи
- Обидва типи reference мають поле
current, яке можна змінювати. createRefстворює новий об’єкт при кожному рендері, тому його не слід використовувати в циклі рендеру.useRefстворюється один раз при монтуванні і зберігає значення, що дозволяє уникнути зайвих перерисувань.
Як це працює
- При
createRefReact під час рендеру присвоює DOM‑елементуref.current. - При
useRefReact просто зберігає об’єкт, і після рендеруref.currentоновлюється.
Практика і реалізація
// Класовий компонент
class MyComponent extends React.Component {
inputRef = createRef<HTMLInputElement>();
render() {
return <input ref={this.inputRef} />;
}
}
// Функціональний компонент
function MyComponent() {
const inputRef = useRef<HTMLInputElement>(null);
return <input ref={inputRef} />;
}
Тестування
- Для
createRefможна перевірити, щоthis.inputRef.currentмістить DOM‑елемент після монтуючого життєвий цикл. - Для
useRefтестують, що значення не змінюється між рендерами:expect(inputRef.current).toBeDefined();.
Особливості в контексті React
createRefчасто використовується у класах, коли потрібна нова reference на кожен рендер (наприклад, у списках з динамічними елементами).useRefє більш гнучким для функціональних компонентів і дозволяє зберігати будь‑яке мутабельне значення (наприклад, таймери, попередні пропси).
Оптимізація та типові помилки
- Використання
createRefу функціональних компонентах призводить до створення нових об’єктів при кожному рендері, що може вплинути на продуктивність. - Замість
createRefу функціональних компонентах слід застосовуватиuseRef.
Диагностика
- Якщо
ref.currentповертаєnull, перевірте, чи компонент вже монтувався і чи правильно передається атрибутref. - Якщо reference оновлюється занадто часто, перевірте, чи не створюєте ви новий
createRefу циклі рендеру.
Часті помилки (8)
- Використання
createRefу функціональних компонентах. - Передача
refв компонент, який не підтримує forwardRef. - Зміна
currentбез використання state, що не викликає перерисування. - Неочікуване оновлення
currentпід час асинхронних операцій. - Застосування
refдо елементів, що не існують у DOM (наприклад,<Fragment>). - Заміна
refна інший об’єкт без оновлення компонента. - Використання
refу списку без ключа, що призводить до повторного створення reference. - Неочікуване очищення
currentу useEffect без dependency‑масиву.
Cheatsheet
createRef→ класові компоненти, новий об’єкт на рендер.useRef→ функціональні компоненти, стабільний об’єкт між рендерами.ref.current→ DOM‑елемент або будь‑яке мутабельне значення.forwardRef→ передача ref через компонент.
Follow‑up питання
- Як
useRefможна використовувати для зберігання таймеру? - Чому
createRefне підходить для функціональних компонентів?