How to Use React forwardRef in Class Components: A Complete Guide
Wrap your class component with React.forwardRef to forward the ref argument to the class instance via a prop like forwardedRef, allowing parent components to access the class instance's methods and underlying DOM nodes.
The React.forwardRef API enables parent components to obtain refs to child component instances or DOM nodes. While commonly associated with function components, implementing react forwardref in class components requires a specific wrapping pattern to expose the class instance to parent components in the facebook/react repository.
Understanding React forwardRef Internals
According to the React source code, forwardRef is implemented in packages/react/src/ReactForwardRef.js. It creates a special React element type identified by REACT_FORWARD_REF_TYPE. This mechanism allows React to distinguish forwardRef components during reconciliation and properly pass the ref argument separately from props.
When you wrap a class component with forwardRef, the wrapper function receives props and ref as distinct arguments. You must manually pass the ref to the class component through a regular prop (commonly named forwardedRef or innerRef) because the ref attribute is not a real prop and is handled specially by React.
Implementing forwardRef with Class Components
Step 1: Define the Class Component
Create your class component as usual, but prepare it to receive the forwarded ref through a prop. Do not use the reserved ref prop name.
import React from 'react';
class MyInput extends React.Component {
focus() {
this.input?.focus();
}
render() {
// Attach the forwarded ref to the DOM element
return <input ref={this.props.forwardedRef} {...this.props} />;
}
}
Step 2: Create the forwardRef Wrapper
Wrap the class component with React.forwardRef to intercept the ref and pass it down as a regular prop.
const ForwardedMyInput = React.forwardRef((props, ref) => (
<MyInput {...props} forwardedRef={ref} />
));
export default ForwardedMyInput;
Step 3: Consume the Ref in Parent Components
In the parent component, create a ref using React.createRef() (in class components) or useRef() (in function components) and pass it to the wrapped component.
import React, { createRef } from 'react';
import ForwardedMyInput from './ForwardedMyInput';
class Form extends React.Component {
constructor(props) {
super(props);
this.inputRef = createRef();
}
componentDidMount() {
// Access the class instance method
this.inputRef.current.focus();
}
render() {
return (
<div>
<ForwardedMyInput ref={this.inputRef} placeholder="Type here…" />
</div>
);
}
}
Handling Prop Name Collisions
If your class component already uses a prop named forwardedRef for other purposes, use an alternative name like innerRef to avoid collisions.
const ForwardedMyInput = React.forwardRef((props, ref) => (
<MyInput {...props} innerRef={ref} />
));
class MyInput extends React.Component {
render() {
return <input ref={this.props.innerRef} {...this.props} />;
}
}
Key Source Files and Implementation Details
The core implementation of forwardRef resides in packages/react/src/ReactForwardRef.js. This file defines the REACT_FORWARD_REF_TYPE symbol and the logic that allows React to treat the ref argument separately from regular props during the reconciliation process.
The test suite in packages/react/src/__tests__/forwardRef-test.js validates that refs are correctly forwarded to both function and class components, ensuring that instance methods remain accessible to parent components.
Summary
- React.forwardRef creates a special element type that intercepts the
refattribute and passes it as a second argument to the render function. - To use react forwardref in class components, wrap the class with
forwardRefand pass the ref down via a regular prop (e.g.,forwardedReforinnerRef). - The class component attaches the forwarded ref to DOM elements or exposes its own instance methods to the parent.
- Implementation details are found in
packages/react/src/ReactForwardRef.jsand tested inpackages/react/src/__tests__/forwardRef-test.js.
Frequently Asked Questions
Can I use React.forwardRef directly on a class component without a wrapper?
No, you cannot apply React.forwardRef directly to a class component definition. The forwardRef API expects a function that receives (props, ref) as arguments. Class components are instantiated by React, so you must create a functional wrapper that renders the class component and passes the ref via a regular prop like forwardedRef.
What is the difference between using forwardRef with class components versus function components?
With function components, React.forwardRef passes the ref directly as the second argument to the function, which can then attach it to a DOM node or pass it along. With class components, the ref cannot be attached directly to the class instance during instantiation; instead, you must forward the ref through a wrapper function that passes it as a prop to the class component, which then attaches it to internal DOM elements or exposes instance methods.
Why does my class component receive the ref as undefined when using forwardRef?
This typically occurs when you attempt to access this.props.ref inside the class component. The ref attribute is reserved by React and is not passed as a prop to the component. When using the forwardRef pattern with class components, you must explicitly pass the ref under a different prop name (such as forwardedRef or innerRef) in the wrapper function, and then access it via that prop name in the class component.
How do I access instance methods of a class component from the parent using forwardRef?
When you successfully forward a ref to a class component, the parent receives the component instance (not a DOM node). You can then call public methods defined on the class. Ensure the class component assigns the forwarded ref to a DOM element if you need the DOM node, or simply use the ref to access class methods directly. In the parent, use this.componentRef.current.methodName() (for class parents) or componentRef.current.methodName() (for function parents with useRef).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →