Skip to main content

require-memo

Require exported function components to use explicit React memoization.

Deprecated in v2.0.0. This rule is frozen, retained in v3, and scheduled for removal in v4.0.0. Blanket memo requirements are not a sound performance policy and conflict with compiler-managed memoization. Remove the rule during migration; there is no direct replacement.

Targeted pattern scope

This rule checks exported PascalCase functions and function-valued variables that directly contain JSX and have at most two parameters. It recognizes named, aliased, default, and namespace imports of memo and forwardRef from React or preact/compat.

An outer memo(...) wrapper satisfies the rule. forwardRef(...) is unwrapped for component detection but does not itself satisfy the memoization requirement. Non-exported functions, lowercase utilities, functions with more than two parameters, nested-only JSX, and class components are outside the rule's scope.

What this rule reports

The rule reports exported components without an explicit memo(...) boundary. Memoization can skip rendering when props are shallowly equal, but it adds comparison work and does not help when props are always new.

Why this rule exists

Some projects use explicit memo boundaries as part of their public component contract. The rule makes that convention enforceable while leaving the performance decision to profiling and project policy.

❌ Incorrect

export function UserCard({ name }: { name: string }) {
return <article>{name}</article>; // Exported component is not memoized.
}
import { forwardRef } from "react";

export const Input = forwardRef((props, ref) => (
<input {...props} ref={ref} /> // forwardRef alone is not memoization.
));

✅ Correct

import { memo } from "react";

export const UserCard = memo(function UserCard({ name }: { name: string }) {
return <article>{name}</article>;
});
import { forwardRef, memo } from "react";

export const Input = memo(
forwardRef((props, ref) => <input {...props} ref={ref} />)
);

Behavior and migration notes

This rule reports only. Adding memo automatically can regress performance, obscure component names, or imply a stability guarantee that the component's props do not meet.

React Compiler applies automatic component and value memoization in supported builds, reducing the need for manual memo. Enable the legacy rule only when a project intentionally requires explicit memo boundaries while migrating away from that policy.

The rule is deprecated and excluded from minimal, recommended, strict, strictTypeChecked, all, and allStrict. The migration-only allWithDeprecated and allStrictWithDeprecated presets retain it at warning level in v3 so existing configurations can remove the policy before its scheduled removal in v4.0.0.

Options

interface Options {
ignoredComponents?: Readonly<Record<string, boolean>>;
}

Default: { ignoredComponents: {} }

ignoredComponents accepts exact names and minimatch-style glob patterns. true ignores matching components; false explicitly keeps them in scope. Exact entries take precedence over patterns.

// config: { ignoredComponents: { "Internal*": true } }
export const InternalBadge = () => <span>Internal</span>; // Allowed by the glob.

ESLint flat config example

import etcMisc from "eslint-plugin-etc-misc";

export default [
{
plugins: { "etc-misc": etcMisc },
rules: {
"etc-misc/require-memo": ["warn", { ignoredComponents: { "Page*": true } }],
},
},
];

When not to use it

Do not use this rule as a blanket performance policy. Disable it when profiling does not justify memoization, when components usually receive unstable props, or when React Compiler owns memoization.

Package documentation

The rule is a clean-room implementation informed by the public behavior of eslint-plugin-react-usememo. It deliberately omits automatic fixes and does not reuse upstream source.

Rule catalog ID: R084

Further reading

Adoption resources

  • Start at warning level in CI, then move to error after cleanup.
  • Confirm memoization helps with representative profiling before changing a component.