Документация React гласит:
Вы не можете использовать атрибут ref на компонентах функций, потому что у них нет экземпляров. ( больше )
Это означает, что вы не можете привязать свои ссылки к функциональным компонентам. Вот почему ваш ref2.current
равен null
. Если вы хотите привязать ref к компоненту, вам нужно использовать компоненты класса. Ваш ref1
не является ссылкой на компонент Comp1
. На самом деле он содержит объект, который вы передали в useImperativeHandle
hook. то есть он содержит следующий объект:
{
print: () => {
console.log('comp1')
}
}
Вы должны использовать forwardRef
с функциональными компонентами, если вы хотите связать вашу ссылку с каким-либо элементом HTML или компонентом класса, который визуализирует ваш компонент. Или вы можете связать ваш ref с каким-либо объектом с помощью useImperativeHandle
hook.
UPDATE
Использование useImperativeHandle
аналогично добавлению методов к вашему. Компонент класса:
class Comp1 extends React.Component {
print() {
console.log('comp1');
}
render() {
return (<div>comp1</div>)
}
}
совпадает с
const Comp1 = forwardRef((props, ref) => {
useImperativeHandle(ref, () => ({
print: () => {
console.log('comp1')
}
}), []);
return <div>comp1</div>
});
Вы спросили в комментарии:
Итак, после перехода кловушки (и все же избегать использования классов), единственный способ использовать ref - это использовать useImperativeHandle
(и фактически использовать «поддельный» ref)? Это хорошая практика?
Ответ: Использование useImperativeHandle
является такой же плохой практикой, как и вызов методов дочерних компонентов при помощи ссылок в компонентах класса. React doc говорит, что вы должны избегать вызова методов дочерних компонентов по ссылкам, вы должны избегать использования useImperativeHandle
. Кроме того, вы должны избегать использования ссылок, где вы можете делать вещи без них.