Breaking
- Switch from
eslint-plugin-reactto@eslint-react/eslint-plugine1936a8 - Require ESLint 10.4
- Require Node.js 22
- JSX formatting rules now come from
@stylistic/eslint-plugininstead ofeslint-plugin-react - JSX prop ordering now comes from
eslint-plugin-perfectionist, as@stylistic/jsx-sort-propsis deprecated
Improvements
- Add accessibility rules d5e1b27
- Use
line-alignedfor JSX closing bracket and tag location 55754f0 - Add
prettieroption a654d08
Migration guide
What you need to do
Nothing, if you only use the config. Rule names in your eslint-disable comments and any per-rule overrides in your own config need updating.
-// eslint-disable-next-line react/no-danger
+// eslint-disable-next-line @eslint-react/dom-no-dangerously-set-innerhtmlRenamed rules
| Before | After |
|---|---|
react/button-has-type
| @eslint-react/dom-no-missing-button-type
|
react/no-danger
| @eslint-react/dom-no-dangerously-set-innerhtml
|
react/no-danger-with-children
| @eslint-react/dom-no-dangerously-set-innerhtml-with-children
|
react/no-find-dom-node
| @eslint-react/dom-no-find-dom-node
|
react/no-render-return-value
| @eslint-react/dom-no-render-return-value
|
react/no-unknown-property
| @eslint-react/dom-no-unknown-property
|
react/style-prop-object
| @eslint-react/dom-no-string-style-prop
|
react/void-dom-elements-no-children
| @eslint-react/dom-no-void-elements-with-children
|
react/iframe-missing-sandbox
| @eslint-react/dom-no-missing-iframe-sandbox + @eslint-react/dom-no-unsafe-iframe-sandbox (the old rule's two halves are now separate rules)
|
react/jsx-no-script-url
| @eslint-react/dom-no-script-url
|
react/jsx-no-target-blank
| @eslint-react/dom-no-unsafe-target-blank
|
react/no-children-prop
| @eslint-react/jsx-no-children-prop + @eslint-react/jsx-no-children-prop-with-children
|
react/jsx-no-comment-textnodes
| @eslint-react/jsx-no-comment-textnodes
|
react/no-namespace
| @eslint-react/jsx-no-namespace
|
react/jsx-no-useless-fragment
| @eslint-react/jsx-no-useless-fragment
|
react/jsx-key
| @eslint-react/no-missing-key + @eslint-react/no-duplicate-key + @eslint-react/jsx-no-key-after-spread
|
react/no-deprecated
| @eslint-react/no-component-will-mount + -will-receive-props + -will-update, no-create-ref, no-forward-ref, dom-no-render, dom-no-hydrate
|
react/no-unsafe
| @eslint-react/no-unsafe-component-will-mount + -will-receive-props + -will-update
|
react/forward-ref-uses-ref
| @eslint-react/no-forward-ref — stricter: the old rule required a ref parameter, the new one bans forwardRef outright, as React 19 passes ref as a normal prop
|
react/hook-use-state
| @eslint-react/use-state
|
react/jsx-no-constructed-context-values
| @eslint-react/no-unstable-context-value
|
react/no-object-type-as-default-prop
| @eslint-react/no-unstable-default-props
|
react/no-redundant-should-component-update
| @eslint-react/no-unused-class-component-members — also reports unused class methods, which react/no-unused-class-component-methods used to cover
|
react/jsx-no-leaked-render
| @eslint-react/no-leaked-conditional-rendering (TypeScript only)
|
react/no-unused-prop-types
| nothing for now — see below |
react/no-access-state-in-setstate
| @eslint-react/no-access-state-in-setstate
|
react/no-array-index-key
| @eslint-react/no-array-index-key
|
react/no-direct-mutation-state
| @eslint-react/no-direct-mutation-state
|
react/no-did-update-set-state
| @eslint-react/no-set-state-in-component-did-update (plus -did-mount and -will-update)
|
react/no-unused-state
| @eslint-react/no-unused-state
|
react/self-closing-comp
| @stylistic/jsx-self-closing-comp
|
react/jsx-pascal-case
| @stylistic/jsx-pascal-case
|
react/jsx-sort-props
| perfectionist/sort-jsx-props
|
react/jsx-props-no-multi-spaces
| @stylistic/no-multi-spaces, already enabled by eslint-config-xo
|
every other react/jsx-* formatting rule
| the same name under @stylistic/
|
Removed rules
These have no equivalent in ESLint React, @stylistic or perfectionist, and are now gone:
react/jsx-no-duplicate-props— the one worth knowing about.<div className="a" className="b"/>no longer reports in.jsx. TypeScript still catches it in.tsx.react/jsx-boolean-value—<Foo bar={true}/>no longer reportsreact/jsx-fragments—<React.Fragment>no longer reportsreact/no-unescaped-entitiesreact/function-component-definitionreact/jsx-no-bindreact/jsx-props-no-spread-multireact/boolean-prop-namingreact/checked-requires-onchange-or-readonlyreact/no-invalid-html-attributereact/no-typosreact/no-this-in-sfcreact/no-string-refsreact/no-is-mountedreact/prefer-read-only-props- The
propTypesand class-component family:prop-types,require-default-props,default-props-match-prop-types,state-in-constructor,static-property-placement,no-arrow-function-lifecycle