Что такое useImperativeHandle в React?
useImperativeHandle
useImperativeHandle используется совместно с forwardRef и позволяет явно контролировать, какие методы или свойства будут доступны через ref для родительского компонента. По умолчанию при передаче ref через forwardRef родитель получает прямой доступ к DOM-узлу дочернего компонента. useImperativeHandle позволяет заменить этот доступ кастомным API.
Сигнатура хука
useImperativeHandle(ref, createHandle, dependencies?);
ref— ref, переданный из родителя черезforwardRefcreateHandle— функция, возвращающая объект с методами/свойствами, которые увидит родительdependencies— массив зависимостей (аналогичноuseEffect)
Когда применять
Хук нужен, когда компонент хочет предоставить родителю конкретное, ограниченное API, а не весь DOM-узел целиком. Это соответствует принципу инкапсуляции: дочерний компонент контролирует, что именно доступно снаружи.
Типичные сценарии:
- Модальное окно с методами
open()иclose() - Поле ввода с методами
focus()иclear() - Анимационный компонент с методом
play()
Пример: кастомный инпут
import { forwardRef, useRef, useImperativeHandle } from 'react';
interface InputHandle {
focus: () => void;
clear: () => void;
}
// Дочерний компонент раскрывает только focus и clear
const CustomInput = forwardRef<InputHandle, React.InputHTMLAttributes<HTMLInputElement>>(
(props, ref) => {
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle(ref, () => ({
focus() {
inputRef.current?.focus();
},
clear() {
if (inputRef.current) {
inputRef.current.value = '';
}
},
}));
return <input ref={inputRef} {...props} />;
}
);
// Родительский компонент
function Form() {
const inputRef = useRef<InputHandle>(null);
const handleReset = () => {
inputRef.current?.clear();
inputRef.current?.focus();
};
return (
<div>
<CustomInput ref={inputRef} placeholder="Введите текст" />
<button onClick={handleReset}>Сбросить</button>
</div>
);
}
Важные нюансы
Зависимости. Если методы в createHandle используют переменные из замыкания, их нужно добавить в массив зависимостей, иначе хук будет работать с устаревшими значениями.
Ограниченность API. Родитель не может обратиться к DOM-узлу напрямую — он видит только то, что вернула createHandle. Это защищает внутреннее устройство компонента.
Не злоупотребляйте. useImperativeHandle нарушает декларативный стиль React. Используйте его только тогда, когда управление через пропсы и состояние неудобно или невозможно (например, для триггерных действий вроде фокуса, скролла, воспроизведения анимации).
Что хочет услышать интервьюер
Кандидат знает, что хук работает только в связке с forwardRef
Понимание цели хука — ограничить доступ родителя к внутреннему DOM и предоставить кастомное API
Знание сигнатуры: три аргумента — ref, createHandle, dependencies
Осознание, что это императивный инструмент и его применение должно быть оправдано
Умение привести конкретный сценарий использования: модалка, input с focus/clear, анимации
Пример: Модальное окно с кастомным API через useImperativeHandle
import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
interface ModalHandle {
open: () => void;
close: () => void;
}
// Модальное окно раскрывает только open и close
const Modal = forwardRef<ModalHandle>((_, ref) => {
const [isOpen, setIsOpen] = useState(false);
useImperativeHandle(ref, () => ({
open() {
setIsOpen(true);
},
close() {
setIsOpen(false);
},
}));
if (!isOpen) return null;
return (
<div className="modal">
<p>Содержимое модального окна</p>
</div>
);
});
// Родительский компонент управляет модалкой через ref
function App() {
const modalRef = useRef<ModalHandle>(null);
return (
<div>
<button onClick={() => modalRef.current?.open()}>Открыть</button>
<button onClick={() => modalRef.current?.close()}>Закрыть</button>
<Modal ref={modalRef} />
</div>
);
}
Типичные ошибки
Путают useImperativeHandle с простым forwardRef — думают, что forwardRef сам по себе достаточен для кастомного API
Забывают указать зависимости, из-за чего методы работают с устаревшими данными из замыкания
Используют хук там, где достаточно пропсов и состояния — это противоречит декларативному подходу React
Не типизируют handle-объект при работе с TypeScript, теряя подсказки и безопасность типов
Применяют хук без forwardRef, что приводит к ошибке в рантайме


