logoESLint React
Custom Rules

No createRef

Disallow React.createRef() in favor of useRef.

Rule Code

Copy and paste this into your eslint.config.ts:

import eslintJs from "@eslint/js";
import { defineConfig as defineReactConfig, merge } from "@eslint-react/kit";
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";

export default defineConfig(
  {
    files: ["**/*.{ts,tsx}"],
    extends: [
      eslintJs.configs.recommended,
      tseslint.configs.recommended,
      defineReactConfig(
        {
          name: "no-create-ref",
          make: (ctx, kit) => {
            const isCreateRefCall = kit.is.reactAPICall("createRef");

            return {
              CallExpression(node) {
                if (isCreateRefCall(ctx, node)) {
                  ctx.report({
                    node,
                    message: "Don't use 'createRef'. Use the 'useRef' hook instead.",
                  });
                }
              },
            };
          },
        },
      ),
    ],
  },
);

Examples

❌ Invalid

import React from "react";

class MyComponent extends React.Component {
  ref = React.createRef<HTMLDivElement>();

  render() {
    return <div ref={this.ref}>Hello</div>;
  }
}
import { createRef } from "react";

const ref = createRef<HTMLInputElement>();

✅ Valid

import { useRef } from "react";

function MyComponent() {
  const ref = useRef<HTMLDivElement>(null);
  return <div ref={ref}>Hello</div>;
}

How It Works

This rule uses kit.is.reactAPICall("createRef") to create a predicate that identifies calls to React.createRef() (including bare createRef() imports). Unlike collector-based rules, this rule works as a simple AST visitor — it checks every CallExpression node directly, with no need for a collector or merge.

kit.is.reactAPICall is a factory: you pass any React API name and get back a predicate that handles all import styles (namespace import, named import, etc.). For common APIs, pre-built predicates are also available directly on kit.is — for example kit.is.memoCall, kit.is.forwardRefCall, kit.is.createElementCall.

Customization Ideas

  • Extend to also ban React.createRef as an identifier reference (not just calls), using kit.is.reactAPI("createRef")
  • Add auto-fix to convert createRef() to useRef(null) inside function components
  • Ban other legacy APIs like createElement using the pre-built kit.is.createElementCall predicate

On this page