Що робить forwardRef()?
Що робить forwardRef()
forwardRef() дозволяє передавати ref (посилання) через компонент далі - до його дочірнього елемента.
Простіше кажучи: зазвичай ref працює лише з DOM-елементами (
<input>,<div>,<video>), але не з твоїми компонентами (<MyInput />).forwardRef «пробрасує» ref усередину твого компонента, щоб він таки «дійшов» до потрібного DOM-вузла.
Без forwardRef ref не працює
function MyInput() {
return <input />;
}
function App() {
const inputRef = useRef(null);
// This won't work: the ref won't reach inside MyInput
return <MyInput ref={inputRef} />;
}Помилка в консолі:
Warning: Function components cannot be given refs.React не знає, куди прикріпити ref, тому що MyInput - це звичайна функція, а не DOM-елемент.
З forwardRef
import { forwardRef, useRef, useEffect } from "react";
const MyInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
function App() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // now it works!
}, []);
return <MyInput ref={inputRef} placeholder="Focus on me" />;
}Тепер ref із App «пробрасується» прямо до внутрішнього <input>.
Як це працює
forwardRef приймає компонент як аргумент і повертає новий компонент, який може отримувати ref як другий параметр:
const MyComponent = forwardRef((props, ref) => {
// ref is now available here
return <div ref={ref}>{props.children}</div>;
});Приклад із useImperativeHandle
Іноді ти хочеш керувати тим, що саме доступно через ref, а не просто DOM.
import { useRef, useImperativeHandle, forwardRef } from "react";
const Timer = forwardRef((props, ref) => {
const startTime = useRef(Date.now());
useImperativeHandle(ref, () => ({
reset: () => (startTime.current = Date.now()),
getElapsed: () => Date.now() - startTime.current,
}));
return <p>Timer running...</p>;
});
function App() {
const timerRef = useRef();
return (
<div>
<Timer ref={timerRef} />
<button onClick={() => console.log(timerRef.current.getElapsed())}>
Show elapsed time
</button>
<button onClick={() => timerRef.current.reset()}>Reset</button>
</div>
);
}Тут forwardRef + useImperativeHandle дають повний контроль: ти пробрасуєш не просто DOM, а набір методів, які батьківський компонент може викликати.
Важливо пам'ятати
| Правило | Пояснення |
|---|---|
| ref типово не передається у функціональні компоненти | Лише DOM-елементи приймають ref напряму |
| forwardRef потрібен, щоб пробросити ref усередину | Дозволяє батьківському компоненту керувати дочірнім елементом |
| Другий аргумент функції - це ref | forwardRef((props, ref) => {...}) |
| Працює лише з функціями, не з класами | Для класів ref працює напряму |
Підсумок
| Питання | Відповідь |
|---|---|
| Що робить forwardRef() | Дозволяє передавати ref через компонент усередину до дочірнього елемента |
| Як виглядає | const Comp = forwardRef((props, ref) => ) |
| Коли використовувати | Коли потрібно, щоб батьківський компонент мав доступ до DOM-елемента всередині кастомного компонента |
| Можна комбінувати з | useImperativeHandle() - щоб керувати тим, що доступно через ref |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.