Stop using forwardRef() in your custom components in React

In React, forwardRef lets your component expose a DOM node to parent component with a ref. To let your component receive a ref and forward it to a child component, we call forwardRef().

import { forwardRef } from 'react';

const MyInput = forwardRef(function MyInput(props, ref){
  return {...}
})

forwardRef accepts a render function as an argument. React calls this function with props and ref:

const MyInput = forwardRef(function MyInput(props, ref){
  return (
    <div>
      <label>{props.label}</label>
      <input ref={ref}>
    </div>
  )
})

forwardRef returns a React component that you can render in JSX. Unlike React components defined as plain functions, the component returned by forwardRef is able to take a ref prop.

By default, each component’s DOM nodes are private. However, sometimes it’s useful to expose a DOM node to the parent—for example, to allow focusing it. ref can be an object or a function, its default value is null.

Passing ref without using forwardRef

Now the question is, why do we have to wrap custom component with forwardRef to receive a ref prop in the component, can't just ref just be a prop? Simply rename ref prop to something else,like inputRef in our example:

function MyInput(props) {
  const { inputRef, label, ...otherProps } = props
  return (
    <div>
      <label>{label}</label>
      <input {...otherProps} ref={inputRef} />
    </div>
  )
}

Now in our <Form /> component:

import { useRef } from 'react'

function Form() {
  const inputRef = useRef(null)

  return (
    <form>
      <MyInput label="Enter your name:" inputRef={inputRef} />
      <button type="button" onClick={handleClick}>
        Submit
      </button>
    </form>
  )
}

That's all we have do to get rid of using forwardRef() from our codebase and life too :p. Is there any benefit associated with using forwardRef()? NO! A refis an object, passing it through a custom component shouldn't be anything special.

In fact, Andrew Clark (Reactjs core team member), responded to a question (why does forwardRef() exit? Why can't just be a prop?) on X (still Twitter):

That is the eventual plan, but it’s a breaking change so to minimize churn we’re going to group it together with other JSX-related breaking changes we have planned, like removing defaultProps. forwardRef was the stepping stone solution when we introduced hooks. The time is nigh.

In the future, passing a ref as a prop will just work and forwardRef will no longer be required. Let's look forward to React19!!!

Ref Links