no-create-ref
Disallows 'createRef' in function components and Hooks.
Full Name in eslint-plugin-react-x
react-x/no-create-refFull Name in @eslint-react/eslint-plugin
@eslint-react/no-create-refPresets
x
recommended
recommended-typescript
recommended-type-checked
strict
strict-typescript
strict-type-checked
Rule Details
createRef() is a legacy API that is not recommended for use in new code. Instead, prefer using useRef() with function components.
This rule only reports createRef calls located inside a function component or a Hook. Calls in other locations, such as at the module top-level or inside plain utility functions and class components, are not reported.
Examples
Using createRef in function components
In function components, prefer the Hook useRef over createRef, which was designed for class components.
import React, { createRef } from "react";
// Problem: Using createRef in a function component
function MyComponent() {
const ref = React.createRef<HTMLDivElement>();
// ^^^ [Deprecated] Use 'useRef' instead.
return <div ref={ref} />;
}import React, { useRef } from "react";
// Recommended: Use useRef in function components
function MyComponent() {
const ref = useRef<HTMLDivElement>(null);
return <div ref={ref} />;
}Migrating from createRef to useRef
When migrating a class component to a function component, replace createRef with useRef.
// Problem: createRef inside a function component creates a new ref on every render
import { createRef } from "react";
function Form() {
const inputRef = createRef(); // Does not persist across renders
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus the input</button>
</>
);
}// Recommended: useRef persists the same ref object across renders
import { useRef } from "react";
function Form() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<input ref={inputRef} />
<button onClick={handleClick}>Focus the input</button>
</>
);
}Using a typed ref with useRef
When you need a strongly typed ref in a function component, use useRef with an explicit generic parameter instead of createRef.
// Recommended: Use useRef with an explicit type parameter
import { useRef } from "react";
function VideoPlayer() {
const videoRef = useRef<HTMLVideoElement>(null);
function handlePlay() {
videoRef.current?.play();
}
function handlePause() {
videoRef.current?.pause();
}
return (
<>
<video ref={videoRef} src="/video.mp4" />
<button onClick={handlePlay}>Play</button>
<button onClick={handlePause}>Pause</button>
</>
);
}Using createRef in Hooks
The rule also applies inside custom Hooks. Prefer useRef so the ref persists across renders.
import { createRef } from "react";
// Problem: Using createRef inside a custom Hook
function useInputRef() {
const ref = createRef<HTMLInputElement>();
// ^^^ [Deprecated] Use 'useRef' instead.
return ref;
}import { useRef } from "react";
// Recommended: Use useRef inside a custom Hook
function useInputRef() {
const ref = useRef<HTMLInputElement>(null);
return ref;
}Using createRef in class components
createRef can still be used in class components, which is the intended use of this API.
import React, { createRef } from "react";
// OK: Using createRef in a class component is the intended use
class MyComponent extends React.Component {
inputRef = createRef();
// ...
}Using createRef outside components and Hooks
Calls outside of function components and Hooks are not reported, since useRef cannot be used there.
import { createRef } from "react";
// OK: Module top-level is not a function component or Hook
const ref = createRef<HTMLDivElement>();
// OK: Plain utility functions are not function components or Hooks
function createRefHolder() {
return createRef();
}Versions
Resources
Further Reading
See Also
react-naming-convention/ref-name
Enforces identifier names assigned fromuseRefcalls to be eitherrefor end withRef.react-x/no-forward-ref
Replaces usage offorwardRefwith passingrefas a prop.react-x/refs
Validates correct usage of refs by checking thatref.currentis not read or written during render.