Announcing v3.0.0
A major release with new rules ported from eslint-plugin-react-hooks, consolidated packages, and ESLint v10 support
This release consolidates all changes from v2.13.0 through v3.0.0.
ESLint v10 and Node.js 22
v3.0.0 embraces the latest tooling ecosystem with the following environment changes:
- Node.js 22+: The minimum required Node.js version is now
>=22.0.0(previously>=20.19.0). - ESLint v10: Bumped to ESLint 10.0.3, leveraging native JSX reference tracking and variable tracking that make several legacy rules redundant.
Package Consolidation
To simplify the plugin ecosystem, v3.0.0 removes the eslint-plugin-react-hooks-extra package entirely. All of its rules have been migrated into eslint-plugin-react-x:
Old Rule (react-hooks-extra/) | New Rule (react-x/) | Change |
|---|---|---|
no-direct-set-state-in-use-effect | set-state-in-effect | relocated, renamed |
Additionally, the react-naming-convention/use-state rule has been moved to react-x/use-state, and react-naming-convention/component-name has been removed.
Consolidated and Removed Rules
Several rules have been consolidated into more powerful replacements, and rules made redundant by ESLint v10 have been removed:
Old Rule (react-x/) | New Rule (react-x/) | Change |
|---|---|---|
jsx-no-duplicate-props | — | removed |
jsx-no-iife | unsupported-syntax | consolidated |
jsx-no-undef | — | removed |
jsx-uses-react | — | removed |
jsx-uses-vars | — | removed |
no-unnecessary-key | — | removed |
no-useless-forward-ref | no-forward-ref | consolidated |
prefer-read-only-props | immutability | consolidated |
prefer-use-state-lazy-initialization | use-state | consolidated |
Key rationale:
jsx-no-undef,jsx-uses-react,jsx-uses-vars: ESLint v10.0.0 now tracks JSX references and variables natively.no-useless-forward-ref: Consolidated intono-forward-ref. Since React 19,forwardRefis no longer necessary asrefcan be passed as a prop.prefer-read-only-props: Replaced by the newimmutabilityrule, which covers a broader set of immutability violations.prefer-use-state-lazy-initialization: Merged intouse-stateand controlled by theenforceLazyInitializationoption (default:true).
Previously deprecated rules have also been removed:
| Rule | Deprecated in | Package |
|---|---|---|
filename-extension | 2.13.0 | eslint-plugin-react-naming-convention |
filename | 2.13.0 | eslint-plugin-react-naming-convention |
no-default-props | 2.9.3 | eslint-plugin-react-x |
no-forbidden-props | 2.3.2 | eslint-plugin-react-x |
no-prop-types | 2.9.3 | eslint-plugin-react-x |
no-string-refs | 2.9.3 | eslint-plugin-react-x |
no-unnecessary-use-ref | 2.10.0 | eslint-plugin-react-x |
Introducing Powerful New Rules
This release adds a significant number of new rules to eslint-plugin-react-x, including rules ported verbatim from eslint-plugin-react-hooks with full code-path analysis, as well as re-implemented React Compiler rules that offer better performance and, unlike the official plugin, require no Babel or React Compiler installation:
react-x/component-hook-factories: Validates against higher-order functions defining nested components or hooks. Components and hooks should be defined at the module level.react-x/error-boundaries: Validates usage of Error Boundaries instead of try/catch for errors in child components.react-x/exhaustive-deps: Enforces that React hook dependency arrays contain all reactive values used in the callback.react-x/immutability(Experimental): Validates against mutating props, state, and other immutable values. Detects in-place array mutations (e.g.push,sort,splice) and direct property assignments on state variables.react-x/purity(Experimental): Validates that components and hooks are pure by checking that they do not call known-impure functions during render.react-x/refs(Experimental): Validates correct usage of refs by checking thatref.currentis not read or written during render.react-x/rules-of-hooks: Enforces the Rules of Hooks. Ported fromeslint-plugin-react-hookswith code-path analysis for more accurate hook validation.react-x/set-state-in-effect: Validates against callingsetStatesynchronously in an effect, which can lead to re-renders that degrade performance. Unlike the oldno-direct-set-state-in-use-effect, this rule allowssetStatewhen the value is derived from a ref (aligning with React's recommended patterns).react-x/set-state-in-render(Experimental): Validates against unconditionally setting state during render, which can cause infinite render loops.react-x/unsupported-syntax: Validates against syntax that React Compiler does not support, includingeval,withstatements, and IIFEs in JSX.react-x/use-memo: Validates thatuseMemois called with a callback that returns a value and that its return value is not discarded.
Experimental Rules
react-x/no-implicit-ref: Prevents implicitly passingrefvia spread props (e.g.,{...values}).react-x/no-implicit-children: Prevents implicitly passingchildrenvia spread props (e.g.,{...values}).react-x/unstable-rules-of-props: Validates against mixing controlled and uncontrolled prop patterns and detects duplicate props on JSX elements. Supports genericfoo/defaultFooprop pairs.react-x/unstable-rules-of-state: Consolidates state-related validations includingprefer-set-state-callback.
New compilationMode Setting
Added support for the compilationMode setting under settings["react-x"]. This setting informs rules about the React Compiler compilation mode your project uses, allowing rules to understand how components and hooks will be optimized by the compiler. Possible values: "infer", "annotation", "syntax", "all".
Developer Experience Improvements
- Safer React 19 migration fixes: The
no-context-provider,no-forward-ref, andno-use-contextrules no longer auto-fix via--fix. Their fixes have been converted to suggestions to prevent automatic code modifications that could break existing code. - Better rule categorization: Many rules have been recategorized from
problemtosuggestiontype for clearer intent. disable-conflict-eslint-plugin-react-hooksconfiguration: Added to both@eslint-react/eslint-pluginandeslint-plugin-react-xfor easier migration fromeslint-plugin-react-hooks.- Improved component detection: Better detection of components created via conditional (ternary) expressions,
satisfiesexpressions, and other TypeScript type patterns.
Migration Guide
Node.js
- Upgrade Node.js to
>=22.0.0(previously>=20.19.0).
Package Changes
- Remove
eslint-plugin-react-hooks-extrafrom yourpackage.json— this package is no longer published. - If you were importing
eslint-plugin-react-hooks-extradirectly, replace it witheslint-plugin-react-x.
ESLint Configuration
- Replace
react-hooks-extra/no-direct-set-state-in-use-effectwithreact-x/set-state-in-effect. - Replace
react-naming-convention/use-statewithreact-x/use-state. - Remove references to the following deleted rules (use
no-restricted-syntaxinstead if needed):react-x/no-default-propsreact-x/no-forbidden-propsreact-x/no-prop-typesreact-x/no-string-refs
- Remove the following removed/consolidated rules from your config if present:
react-x/jsx-no-duplicate-propsreact-x/jsx-no-undefreact-x/jsx-uses-reactreact-x/jsx-uses-varsreact-x/no-unnecessary-keyreact-x/no-unnecessary-use-refreact-x/jsx-no-iife→ usereact-x/unsupported-syntaxreact-x/no-useless-forward-ref→ usereact-x/no-forward-refreact-x/prefer-read-only-props→ usereact-x/immutabilityreact-x/prefer-use-state-lazy-initialization→ usereact-x/use-statereact-naming-convention/filenameandreact-naming-convention/filename-extensionreact-naming-convention/component-name
- Be aware that
react-x/no-context-provider,react-x/no-forward-ref, andreact-x/no-use-contextno longer auto-fix via--fix— apply fixes manually.
Settings
- If your project uses React Compiler, consider adding the
compilationModesetting undersettings["react-x"].
Review New Rules Enabled in Presets
If you use the recommended, x, or all preset, the following rules are now included automatically:
| Rule | Severity | Presets |
|---|---|---|
react-x/component-hook-factories | error | recommended, x |
react-x/error-boundaries | error | recommended, x |
react-x/exhaustive-deps | warn | recommended, x |
react-x/immutability | error | all |
react-x/no-unused-class-component-members | warn | recommended, x |
react-x/purity | warn | recommended, x |
react-x/refs | error | all |
react-x/rules-of-hooks | error | recommended, x |
react-x/set-state-in-effect | warn | recommended, x |
react-x/set-state-in-render | error | recommended, x |
react-x/unsupported-syntax | error | recommended, x |
react-x/use-memo | error | recommended, x |
react-x/use-state | warn | recommended, x |
Migrating from eslint-plugin-react-hooks
See the complete migration guide for step-by-step instructions on replacing eslint-plugin-react-hooks with eslint-plugin-react-x.
References
- Changelog: v3.0.0
- Full Changelog: v2.13.0...v3.0.0