Skip to main content

Що робить forwardRef()?

Що робить forwardRef()

forwardRef() дозволяє передавати ref (посилання) через компонент далі - до його дочірнього елемента.

Простіше кажучи: зазвичай ref працює лише з DOM-елементами (<input>, <div>, <video>), але не з твоїми компонентами (<MyInput />).

forwardRef «пробрасує» ref усередину твого компонента, щоб він таки «дійшов» до потрібного DOM-вузла.


Без forwardRef ref не працює

javascript
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} />; }

Помилка в консолі:

javascript
Warning: Function components cannot be given refs.

React не знає, куди прикріпити ref, тому що MyInput - це звичайна функція, а не DOM-елемент.


З forwardRef

javascript
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 як другий параметр:

javascript
const MyComponent = forwardRef((props, ref) => { // ref is now available here return <div ref={ref}>{props.children}</div>; });

Приклад із useImperativeHandle

Іноді ти хочеш керувати тим, що саме доступно через ref, а не просто DOM.

javascript
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 усерединуДозволяє батьківському компоненту керувати дочірнім елементом
Другий аргумент функції - це refforwardRef((props, ref) => {...})
Працює лише з функціями, не з класамиДля класів ref працює напряму

Підсумок

ПитанняВідповідь
Що робить forwardRef()Дозволяє передавати ref через компонент усередину до дочірнього елемента
Як виглядаєconst Comp = forwardRef((props, ref) =>
)
Коли використовуватиКоли потрібно, щоб батьківський компонент мав доступ до DOM-елемента всередині кастомного компонента
Можна комбінувати зuseImperativeHandle() - щоб керувати тим, що доступно через ref

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.