React Compiler Compatibility Linting

React Compiler compatibility linting uses `eslint-plugin-react-hooks` to detect React patterns that violate assumptions the compiler needs for safe optimization. The diagnostics can identify code the compiler will skip while allowing compatible parts of an application to remain optimized.

React Compiler performs static analysis to optimize components and Hooks, primarily through automatic memoization. That analysis depends on React programming rules such as purity, immutability, correct Hook usage, and predictable data flow. The official `eslint-plugin-react-hooks` now surfaces compiler-related diagnostics alongside traditional Rules of Hooks checks.

A compiler diagnostic does not necessarily mean the entire application cannot use React Compiler. When the compiler finds an unsupported pattern in a component or Hook, it can skip optimization for that unit while continuing to optimize other code. This makes the linting system useful for incremental adoption rather than requiring every warning to be eliminated before enabling compilation.

The rules cover several classes of compatibility problems. Examples include mutating props or state, changing globals during render, using known impure operations such as `Date.now()` during render, reading or writing refs during render, unsupported syntax, and calling libraries whose APIs conflict with React's memoization model.

The plugin also protects existing manual memoization. React Compiler can preserve `useMemo`, `useCallback`, and `React.memo` when its analysis is compatible with them, while incomplete dependency information can prevent further optimization. This is why a compiler-aware lint failure can expose both a compilation limitation and an underlying correctness or maintainability problem.

For current projects, the official plugin provides recommended configurations containing compiler-related rules. The `recommended-latest` preset is intended for trying the latest compiler rules, while the exact rule set can change as the plugin evolves; avoid assuming that every rule exists in every historical plugin release.

Key points

Interview questions

What problem does React Compiler compatibility linting solve?

It identifies code patterns that conflict with assumptions React Compiler needs for safe optimization. The main mechanism is `eslint-plugin-react-hooks`, which reports compiler diagnostics together with traditional React lint rules. Examples include impure rendering, mutations, unsupported syntax, and problematic library APIs. The goal is to make compiler compatibility visible during development rather than discovering problems only after compilation.

What happens when React Compiler finds an unsupported component?

The compiler can skip optimizing the affected component or Hook rather than abandoning optimization for the whole application. This allows compatible portions of a codebase to continue receiving compiler optimizations. The corresponding ESLint diagnostic tells the developer where the unsupported pattern was detected. This behavior supports incremental adoption and gradual cleanup of an existing application.

Why does mutating a global during render conflict with React Compiler?

React expects rendering to be pure, meaning rendering should not produce uncontrolled external mutations. A global is outside React's state and rendering model, so changing it during render makes output depend on external mutable state. That makes static reasoning and memoization less reliable. The compiler-aware `globals` rule specifically checks for these mutations.

How can a third-party library interfere with React Compiler?

A library can expose APIs whose values change internally without changing their object identity, a pattern sometimes called interior mutability. React Compiler's memoization assumes values can be reasoned about according to React's reactive model, so such APIs can make memoized results stale. The `incompatible-library` rule identifies known problematic APIs and allows the compiler to avoid optimizing affected code. Developers should prefer a library API that follows React's model when one exists.

How does compiler linting relate to existing manual memoization?

React Compiler does not simply assume that every existing memoization call is unnecessary. Its analysis accounts for existing `useMemo`, `useCallback`, and `React.memo`, and the preservation rule checks whether that manual memoization can be safely understood. Incorrect dependency lists can prevent the compiler from understanding data flow and may already represent a correctness problem. Therefore, compiler migration is not just about deleting memoization; it is also about making existing memoization semantically correct.