createRef
Creates a mutable ref object for a class component to hold a DOM node or arbitrary value.
createRef()- Added in React 16.3.0
Return value
{ current: null }A new object with a single `current` property, initially `null`. When passed as a `ref` attribute, React sets `current` to the corresponding DOM node or class instance.
Errors
Reading `.current.focus()` before the node has mounted, or after it unmounted, throws because `current` is null.
Changelog
- PHP 16.3.0Introduced as the object-ref replacement for string refs such as ref="input".
- PHP 19.0Ref callbacks may return a cleanup function; a ref object passed to a function component now arrives as an ordinary `ref` prop with no forwardRef needed.
This is the class-component equivalent of useRef. Create the ref once — as a class field or in the constructor — pass it to a JSX node's ref attribute, and React writes the DOM node into current on mount and null on unmount.
When to reach for it
Only inside class components, or in module scope where you need a stable ref object outside any component. In a function component use useRef: it returns the same object across renders, whereas calling this on every render would create a fresh { current: null } each time and lose whatever React had stored.
What trips people up
current is null during the first render and during constructor and render. It is only populated by the time componentDidMount runs, so measuring or focusing must happen there or later, in an event handler. Attaching a ref to a class component gives you the component instance, not a DOM node — to reach the DOM you need a ref inside that component too. Attaching one to a function component passes it through as a regular ref prop in React 19; before that it needed forwardRef.
Example
When to use it
- Focus a text input from a button handler in a class component
- Measure an element's size after mount in legacy class code
- Store a mutable value on a class instance that must not trigger re-renders
Frequently asked questions
Should I use createRef or useRef?
Use useRef in function components and createRef in class components. createRef returns a brand new object on every call, so inside a function component body it would be recreated on each render and lose its value.
Why is my ref's current null?
React only assigns current after the element mounts, so it is null during the constructor and render, and again after unmount. Read it in componentDidMount or in an event handler.
Can I put a ref on a function component?
In React 19 yes — the ref arrives as an ordinary `ref` prop that the component must attach to a node itself. Before React 19 the component had to be wrapped in forwardRef.
More examples
The function-component equivalent
Identical behaviour without a class. Swapping useRef for createRef here would build a new empty ref object on every render, so `current` would be null again after the first state update.
import { useRef, useState } from 'react';
export default function Form() {
// useRef, not createRef: the same object survives every render
const inputRef = useRef(null);
const [info, setInfo] = useState('nothing yet');
function handleFocus() {
inputRef.current.focus();
setInfo('input focused');
}
return (
<div>
<input ref={inputRef} defaultValue="edit me" />
<button onClick={handleFocus}>Focus the input</button>
<p>{info}</p>
</div>
);
}A ref to a class component instance
Two refs are needed: the parent's ref holds the Editor instance, and the Editor's own ref holds the DOM input. Calling this.editorRef.current.focus() reaches the instance method, which then reaches the node.
import { Component, createRef } from 'react';
class Editor extends Component {
constructor(props) {
super(props);
this.inputRef = createRef();
}
// A public method the parent can call
focus() {
this.inputRef.current.focus();
}
render() {
return <input ref={this.inputRef} defaultValue="child input" />;
}
}
class Parent extends Component {
constructor(props) {
super(props);
this.editorRef = createRef();
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// current is the Editor instance, not a DOM node
this.editorRef.current.focus();
}
render() {
return (
<div>
<Editor ref={this.editorRef} />
<button onClick={this.handleClick}>Focus the child</button>
</div>
);
}
}
export default Parent;Holding a value that is not a DOM node
The ref stores a timer id rather than a DOM node, so changing it never triggers a render. componentWillUnmount reads it back to clear the interval — the standard pairing for any subscription set up on mount.
import { Component, createRef } from 'react';
class Ticker extends Component {
constructor(props) {
super(props);
this.timerRef = createRef();
this.state = { ticks: 0 };
}
componentDidMount() {
this.timerRef.current = setInterval(() => {
this.setState((s) => ({ ticks: s.ticks + 1 }));
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timerRef.current);
}
render() {
return <p>{this.state.ticks} ticks</p>;
}
}
export default Ticker;
Discussion