What does forwardRef() do?
What forwardRef() does
forwardRef() lets you pass a ref through a component further down, to its child element.
Put simply: normally ref works only with DOM elements (
<input>,<div>,<video>), but not with your own components (<MyInput />).forwardRef "forwards" the ref into your component so it can still "reach" the right DOM node.
Without forwardRef, ref doesn't work
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} />;
}Console error:
Warning: Function components cannot be given refs.React doesn't know where to attach the ref, because MyInput is just a regular function, not a DOM element.
With 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" />;
}Now the ref from App is "forwarded" directly to the inner <input>.
How it works
forwardRef takes a component as an argument and returns a new component that can receive ref as its second parameter:
const MyComponent = forwardRef((props, ref) => {
// ref is now available here
return <div ref={ref}>{props.children}</div>;
});Example with useImperativeHandle
Sometimes you want to control exactly what's exposed through ref, rather than just the 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>
);
}Here, forwardRef + useImperativeHandle give full control: you forward not just the DOM, but a set of methods that the parent can call.
Important to remember
| Rule | Explanation |
|---|---|
| ref is not passed to functional components by default | Only DOM elements accept ref directly |
| forwardRef is needed to forward ref inward | Lets the parent control the child element |
| The function's second argument is ref | forwardRef((props, ref) => {...}) |
| Works only with functions, not classes | For classes, ref works directly |
Summary
| Question | Answer |
|---|---|
| What forwardRef() does | Lets you pass a ref through a component inward to a child element |
| What it looks like | const Comp = forwardRef((props, ref) => ) |
| When to use it | When the parent needs access to a DOM element inside a custom component |
| Can be combined with | useImperativeHandle() - to control what's exposed through ref |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.