Какие есть Ref в функциональных компонентах?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Ref в функциональных компонентах React
В функциональных компонентах React существуют три основных типа ref, каждый из которых решает определённые задачи и имеет свою специфику использования.
1. useRef() - универсальная ссылка
useRef() — это хук, который возвращает изменяемый ref-объект с свойством .current, инициализированным переданным аргументом. Основные сценарии использования:
Хранение DOM-элементов
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Фокус на input</button>
</div>
);
}
Сохранение изменяемых значений без триггеринга ререндера
function TimerComponent() {
const intervalId = useRef(null);
const [count, setCount] = useState(0);
useEffect(() => {
intervalId.current = setInterval(() => {
setCount(prev => prev + 1);
}, 1000);
return () => clearInterval(intervalId.current);
}, []);
return <div>Счёт: {count}</div>;
}
2. forwardRef() - передача ref через компоненты
forwardRef() позволяет компонентам принимать ref и передавать их дальше дочерним DOM-элементам или компонентам. Это особенно полезно для библиотек компонентов:
import { forwardRef } from 'react';
const CustomInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
function ParentComponent() {
const inputRef = useRef(null);
useEffect(() => {
// Теперь мы имеем доступ к DOM-элементу input
inputRef.current.focus();
}, []);
return <CustomInput ref={inputRef} placeholder="Введите текст" />;
}
3. useImperativeHandle() - кастомизация ref
useImperativeHandle() позволяет кастомизировать значение, которое предоставляется через ref при использовании forwardRef. Вместо предоставления полного доступа к DOM-элементу, мы можем предоставить только определённые методы:
import { forwardRef, useRef, useImperativeHandle } from 'react';
const FancyInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
shake: () => {
// Кастомная анимация
inputRef.current.style.transform = 'translateX(10px)';
setTimeout(() => {
inputRef.current.style.transform = 'translateX(0)';
}, 100);
},
getValue: () => {
return inputRef.current.value;
}
}));
return <input ref={inputRef} {...props} />;
});
function App() {
const fancyInputRef = useRef(null);
const handleClick = () => {
fancyInputRef.current.shake(); // Вызываем кастомный метод
fancyInputRef.current.focus(); // Вызываем стандартный метод
};
return (
<div>
<FancyInput ref={fancyInputRef} />
<button onClick={handleClick}>Взаимодействие</button>
</div>
);
}
Ключевые отличия и рекомендации
useRef— основной инструмент для большинства случаев работы с refforwardRef— необходим для передачи ref через компоненты-обёрткиuseImperativeHandle— для создания контролируемого API компонента через ref
Важные особенности:
- Ref не вызывают ререндер компонента при изменении
- Значение ref сохраняется между рендерами компонента
- Изменение
.currentпроисходит синхронно - Ref работают как замыкания в обработчиках событий
Практические паттерны использования:
// Сохранение предыдущего значения
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
// Измерение размеров DOM-элемента
function useElementSize() {
const ref = useRef(null);
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
if (ref.current) {
const updateSize = () => {
setSize({
width: ref.current.offsetWidth,
height: ref.current.offsetHeight
});
};
updateSize();
window.addEventListener('resize', updateSize);
return () => window.removeEventListener('resize', updateSize);
}
}, []);
return [ref, size];
}
Каждый тип ref решает конкретные задачи в функциональных компонентах, обеспечивая гибкость при работе с DOM, сохранении значений и создании reusable-компонентов. Правильное использование ref позволяет создавать эффективные и производительные React-приложения.