The React.forwardRef function is failing because it’s being passed something that isn’t a valid React component function.

This error typically surfaces when you’re trying to use React.forwardRef to pass a ref down to a child component, but the child component itself isn’t structured correctly to accept a ref. The most common culprit is a class component that doesn’t use React.forwardRef to wrap its definition, or a functional component that’s accidentally defined as a class.

Here are the common causes and how to fix them:

1. Passing ref to a Class Component Not Wrapped in forwardRef

Diagnosis: You’re trying to pass a ref to a class component like this:

class MyClassComponent extends React.Component {
  render() {
    return <input ref={this.props.innerRef} />;
  }
}

const WrappedComponent = React.forwardRef((props, ref) => (
  <MyClassComponent innerRef={ref} />
));

This setup is incorrect because MyClassComponent itself doesn’t know how to receive a ref via props.innerRef in a way that React.forwardRef can manage.

Fix: The class component needs to be the one receiving the ref directly, and you need to use React.forwardRef to wrap the creation of that class component if you want to pass a ref to its instance. However, for class components, you generally forward refs to the DOM element rendered by the class component, not the component instance itself.

class MyClassComponent extends React.Component {
  render() {
    // The ref is attached to the DOM element
    return <input ref={this.props.innerRef} />;
  }
}

// To pass a ref to the *DOM element* inside MyClassComponent
const EnhancedMyClassComponent = React.forwardRef((props, ref) => {
  return <MyClassComponent innerRef={ref} />;
});

// Usage:
const myRef = React.createRef();
<EnhancedMyClassComponent ref={myRef} />

Why it works: React.forwardRef allows you to pass a ref prop through to a child component. When used with class components, the ref is typically attached to a DOM element within the class component’s render method, not to the component instance itself. The innerRef prop in this example is just a custom prop name to pass the ref down; the actual ref attachment happens on the <input> element.

2. Passing ref to a Functional Component Defined as a Class

Diagnosis: You’ve mistakenly defined a functional component using class syntax, and then tried to forward a ref to it.

// Incorrectly defined as a class
class MyFunctionalComponent extends React.Component {
  render() {
    return <input />;
  }
}

// Trying to forward a ref to it
const WrappedComponent = React.forwardRef((props, ref) => (
  <MyFunctionalComponent ref={ref} />
));

Fix: Convert the component to a proper functional component or a class component that correctly handles refs. If it’s intended to be functional, remove the class keyword and render method.

// Correct functional component
function MyFunctionalComponent(props, ref) {
  return <input ref={ref} />;
}

// Forwarding the ref (if MyFunctionalComponent was not defined to accept ref directly)
const WrappedComponent = React.forwardRef((props, ref) => (
  <MyFunctionalComponent ref={ref} {...props} />
));

// Usage:
const myRef = React.useRef();
<WrappedComponent ref={myRef} />

Why it works: Functional components can accept refs directly if they are defined using React.forwardRef. If you’re forwarding a ref to a functional component, that functional component must be structured to receive the ref as its second argument.

3. Misunderstanding forwardRef Usage with Higher-Order Components (HOCs)

Diagnosis: You’ve created a HOC that wraps a component, and you’re trying to forward a ref through the HOC to the wrapped component, but the HOC isn’t correctly forwarding the ref.

const withLogger = (WrappedComponent) => {
  return class extends React.Component {
    render() {
      return <WrappedComponent {...this.props} />;
    }
  };
};

const MyComponent = React.forwardRef((props, ref) => <input ref={ref} />);
const EnhancedComponent = withLogger(MyComponent);

// Trying to use ref on EnhancedComponent
const inputRef = React.useRef();
<EnhancedComponent ref={inputRef} /> // This might not work as expected

Fix: The HOC needs to use React.forwardRef itself to ensure the ref is passed down.

const withLogger = (WrappedComponent) => {
  // The HOC itself must forward the ref
  return React.forwardRef((props, ref) => {
    return <WrappedComponent ref={ref} {...props} />;
  });
};

const MyComponent = React.forwardRef((props, ref) => <input ref={ref} />);
const EnhancedComponent = withLogger(MyComponent);

// Usage:
const inputRef = React.useRef();
<EnhancedComponent ref={inputRef} />

Why it works: When you apply a HOC, the HOC becomes the parent of the component it wraps. If the HOC doesn’t explicitly forward the ref prop, it will be consumed by the HOC’s wrapper component and never reach the intended target. By having the HOC return a component created with React.forwardRef, the ref prop is correctly passed through.

4. Passing a Non-Function/Non-Component to forwardRef

Diagnosis: You’ve accidentally passed a value that isn’t a function or component to React.forwardRef.

// Incorrect: passing a string
const WrappedComponent = React.forwardRef("This is not a component");

// Incorrect: passing a JSX element
const WrappedComponent = React.forwardRef(<div />);

Fix: Ensure the argument passed to React.forwardRef is always a function that accepts props and ref as its arguments.

const MyFunctionalComponent = (props, ref) => {
  return <input ref={ref} />;
};

const WrappedComponent = React.forwardRef(MyFunctionalComponent);

Why it works: React.forwardRef expects a function as its argument. This function will then be treated as a React component that can receive refs.

5. Incorrectly Typing forwardRef with TypeScript

Diagnosis: If you’re using TypeScript, an incorrect type definition for a component that uses forwardRef can lead to this error.

// Incorrect typing
interface MyComponentProps {
  // ... other props
}

const MyComponent = React.forwardRef<HTMLInputElement, MyComponentProps>((props, ref) => {
  return <input ref={ref} {...props} />;
});

Fix: Ensure the types for forwardRef are correctly specified, particularly the ref type.

import React, { Ref } from 'react';

interface MyComponentProps {
  // ... other props
}

// Correct typing:
// The first type argument is the type of the ref (e.g., HTMLInputElement)
// The second type argument is the type of the props
const MyComponent = React.forwardRef<HTMLInputElement, MyComponentProps>(
  (props, ref) => {
    return <input ref={ref} {...props} />;
  }
);

Why it works: TypeScript’s type checking ensures that the ref being forwarded matches the expected type of the DOM element or component instance, preventing runtime errors where an incompatible ref might be passed.

6. Passing a Regular Function (Not a Component Function)

Diagnosis: You have a regular JavaScript function that you intend to use inside a component that accepts a ref, but you’re mistakenly trying to forwardRef to that regular function.

function helperFunction() {
  console.log("This is a helper");
}

// Incorrectly trying to forward ref to a helper
const WrappedComponent = React.forwardRef(helperFunction);

Fix: React.forwardRef is for creating components that can receive refs. Regular utility functions should not be passed to it.

// Define a proper component that accepts a ref
const MyInputComponent = React.forwardRef((props, ref) => {
  return <input ref={ref} {...props} />;
});

// Use your helper function within the component if needed
const MyComponentWithHelper = React.forwardRef((props, ref) => {
  const helperFunction = () => {
    console.log("This is a helper");
  };
  return <input ref={ref} onClick={helperFunction} {...props} />;
});

Why it works: React.forwardRef is designed to create a React component. A plain JavaScript function, even if it takes arguments, isn’t a React component by itself. It needs to be structured within the React.forwardRef wrapper to be recognized as a ref-forwarding component.

The next error you’ll likely encounter if you’ve fixed this is a type error related to the ref itself (e.g., trying to call .focus() on a ref that isn’t an HTMLInputElement) or a prop type mismatch.

Want structured learning?

Take the full React course →