React: forwardRef
By default, React prevents components from reaching into other components. You cannot pass a ref via props directly to a custom component to access its internal DOM nodes.
What is
React.forwardRef, and when do you need to use it?
1. The Problem: Ref is not a standard prop
If you create a standard <input /> element, you can easily attach a ref to it to manage focus. However, if you extract that input into a reusable <CustomInput /> component, passing a ref to it will fail.
import { useRef } from 'react';
// ❌ A standard custom component
function CustomInput({ placeholder }) {
// Where does the ref go? React drops it!
return <input type="text" className="nice-input" placeholder={placeholder} />;
}
function App() {
const inputRef = useRef(null);
// Warning: Function components cannot be given refs.
return <CustomInput ref={inputRef} placeholder="Search..." />;
}React treats key and ref as special reserved keywords. They are stripped out of the props object before it reaches your component.
2. The Solution: React.forwardRef
To allow a parent to pass a ref down into a child component, the child component must explicitly opt-in using the React.forwardRef wrapper.
When you wrap a component in forwardRef, the rendering function receives a second argument: the ref itself!
import { useRef, forwardRef } from 'react';
// ✅ Opt-in to receive the ref as the 2nd parameter
const CustomInput = forwardRef((props, ref) => {
// Now we can attach it directly to the underlying DOM node
return (
<input
ref={ref}
type="text"
className="nice-input"
placeholder={props.placeholder}
/>
);
});
// App works perfectly now!
function App() {
const inputRef = useRef(null);
const handleFocus = () => {
// The parent has full access to the child's raw <input> node
inputRef.current.focus();
};
return (
<>
<CustomInput ref={inputRef} placeholder="Search..." />
<button onClick={handleFocus}>Focus the Input</button>
</>
);
}3. Real-World Use Cases
When building a standard UI library (like Material UI or Chakra UI), developers heavily utilize forwardRef.
If a consumer uses a custom <Button> or <Tooltip> component from your library, they often need access to the underlying DOM node to calculate positions, manage accessibility focus, or integrate with drag-and-drop libraries (like dnd-kit). Wrapping leaf-node components in forwardRef is considered a best practice for generic, reusable UI elements.
Senior-Level Interview Answer
In React,
refis a reserved property that is explicitly excluded from the standardpropsobject to enforce encapsulation. Consequently, attempting to pass a ref to a custom functional component fails by default. To circumvent this and expose an internal DOM node to a parent, the child component must be wrapped inReact.forwardRef(). This higher-order function modifies the component's signature, supplying the forwarded ref as a discrete second parameter alongsideprops. This pattern is fundamentally required when authoring generic, reusable UI primitives (like Inputs or Modals) that consumers might need to imperatively focus, measure, or animate from a higher level in the component tree.
Common Interview Mistakes
❌ Forgetting it's a wrapper
A frequent syntax error during live coding interviews is trying to accept ref inside a standard component declaration without the wrapper wrapper:
// ❌ Syntax Error!
function CustomInput(props, ref) { ... } You must pass the entire function declaration into forwardRef.
❌ Exposing too much control
While forwardRef allows you to expose raw DOM nodes, it breaks encapsulation. If a parent component reaches in and manipulates the DOM styles of a child directly via a ref, it can conflict with React's state-driven renders. A senior developer will combine forwardRef with useImperativeHandle to expose only a highly restricted API (e.g., exposing a .focus() method but hiding the rest of the raw DOM node properties).
