DeployU
Interviews / Frontend Engineering / This custom component is not forwarding its ref. How do you fix it?

Questions

This custom component is not forwarding its ref. How do you fix it?

practical Component Patterns Interactive Quiz Code Examples

A developer has created a reusable CustomInput component. They want to use a ref from a parent component to directly focus this CustomInput when a button is clicked.

However, when they click the “Focus Input” button, nothing happens. If they check the console, they might see a warning like “Function components cannot be given refs. Attempts to access this ref will fail.” or simply find that inputRef.current is null.

The Challenge

You’ve been given the App and CustomInput components.

  1. Explain why the ref is not being forwarded correctly to the internal <input> element.
  2. Fix the CustomInput component using React.forwardRef so that the parent component can successfully focus the input.
Your Code
import React, { useRef } from 'react';

// The CustomInput component - a functional component
function CustomInput(props) {
  // THE BUG: Refs are not automatically passed through functional components.
  // The 'ref' prop here is just a regular prop and won't attach to the <input>.
  return <input type="text" {...props} />;
}

export default function App() {
  const inputRef = useRef(null);

  const focusInput = () => {
    if (inputRef.current) {
      inputRef.current.focus();
      inputRef.current.style.borderColor = 'blue';
    } else {
      console.log("Ref is not attached to the input element!");
    }
  };

  return (
    <div style={{ padding: '20px' }}>
      <h1>Ref Forwarding Example</h1>
      {/* Attempting to pass a ref to a functional component */}
      <CustomInput ref={inputRef} placeholder="Type something..." />
      <button onClick={focusInput} style={{ marginLeft: '10px' }}>
        Focus Input
      </button>
      <p>Click the button to try and focus the input.</p>
    </div>
  );
}
Click "Run Code" to see output...
Click "Run Code" to see test results...

The Solution

Wrong Approach

// The CustomInput component - a functional component function CustomInput(props) { // THE BUG: Refs are not automatically passed through functional components. // The 'ref' prop here is just a regular prop and won't attach to the <input>. return <input type="text" {...props} />; } export default function App() { const inputRef = useRef(null); const focusInput = () => { if (inputRef.current) { inputRef.current.focus(); inputRef.current.style.borderColor = 'blue'; } else { console.log("Ref is not attached to the input element!"); } }; return ( <div style={{ padding: '20px' }}> <h1>Ref Forwarding Example</h1> {/* Attempting to pass a ref to a functional component */} <CustomInput ref={inputRef} placeholder="Type something..." /> <button onClick={focusInput} style={{ marginLeft: '10px' }}> Focus Input </button> </div> ); }

Right Approach

// FIX: Wrap CustomInput with React.forwardRef const CustomInput = forwardRef((props, ref) => { // The 'ref' argument is now the ref passed from the parent. // Attach it to the internal <input> element. return <input type="text" ref={ref} {...props} />; }); export default function App() { const inputRef = useRef(null); const focusInput = () => { if (inputRef.current) { inputRef.current.focus(); inputRef.current.style.borderColor = 'blue'; } else { console.log("Ref is not attached to the input element!"); } }; return ( <div style={{ padding: '20px' }}> <h1>Ref Forwarding Example</h1> {/* Now, passing a ref to CustomInput works correctly */} <CustomInput ref={inputRef} placeholder="Type something..." /> <button onClick={focusInput} style={{ marginLeft: '10px' }}> Focus Input </button> </div> ); }

Why This Works

The problem arises because, by default, React functional components do not automatically “forward” refs to their internal DOM elements. When you pass a ref prop to a custom functional component (like CustomInput), React treats it as a regular prop. It doesn’t know that you intend for that ref to attach to an internal DOM element.

The Fix: Using React.forwardRef

React.forwardRef is a higher-order function that lets you pass a ref through a component to one of its children. It takes a functional component as an argument and returns a new React component that can receive a ref prop and pass it down.

The component wrapped with forwardRef receives props as its first argument and the ref as its second argument. You then attach this ref to the specific DOM element you want to expose.

By using React.forwardRef, the CustomInput component now correctly receives the ref from App and attaches it to its internal <input> element. This allows the App component to directly access and manipulate the <input> element, such as calling its focus() method.

Practice Question

What is the primary purpose of React.forwardRef?