Skip to content

Support ESLint 10 in @react-native/eslint-config - #59071

Open
usama-liaqat wants to merge 1 commit into
react:mainfrom
usama-liaqat:chore/eslint-plugin-latest-eslint
Open

usama-liaqat wants to merge 1 commit into
react:mainfrom
usama-liaqat:chore/eslint-plugin-latest-eslint

Conversation

@usama-liaqat

Copy link
Copy Markdown

Summary:

@react-native/eslint-config declares support for eslint ^8 || ^9, but apps on the latest ESLint (10.x) can't use it. Under ESLint 10:

  • @babel/eslint-parser 7 crashes on every file (scopeManager.addGlobals is not a function). Version 8 supports ESLint 10 but requires @babel/core 8, which Metro doesn't support yet.
  • @react-native/eslint-plugin-specs calls context.getFilename() and context.getSourceCode(), which ESLint 10 removed.
  • eslint-plugin-react, eslint-plugin-react-native, eslint-plugin-ft-flow and the unmaintained eslint-plugin-eslint-comments still use removed rule-context APIs.
  • The locked eslint-plugin-jest pulled in a nested @typescript-eslint/utils 8.39, which crashes on load under ESLint 10.

This PR makes the flat config (@react-native/eslint-config/flat) work on ESLint 9 and 10, and leaves the legacy ESLint 8 config (extends: '@react-native') unchanged:

  • Parser: the flat config parses .js/.jsx with flow-eslint instead of @babel/eslint-parser. It supports Flow and JSX, it's the parser the monorepo already uses, and it doesn't read the app's Babel config. That also fixes a parse error on @flow files when @react-native/babel-preset uses hermes-parser.
  • Legacy plugins: react, react-native and ft-flow are wrapped with fixupPluginRules from @eslint/compat.
  • eslint-comments: the flat config uses the maintained @eslint-community/eslint-plugin-eslint-comments, registered under the same eslint-comments key, so rule names and existing disable comments still work. The legacy config keeps the original plugin.
  • Specs rule: react-native-modules uses context.filename and context.sourceCode, with fallbacks to the method forms for older ESLint 8 releases.
  • no-unused-vars: caughtErrors: 'none' is now set explicitly. That was the ESLint 8 default, so ESLint 9 and 10 report the same as 8.
  • Dependencies: bumped eslint-plugin-jest (^29.17.0), eslint-plugin-react-hooks (^7.1.1) and @typescript-eslint/* (^8.71.2) to versions that support ESLint 10, and refreshed the lockfile so the stale nested @typescript-eslint/utils is deduped.
  • Peer range: eslint is now ^8.0.0 || ^9.0.0 || ^10.0.0.

The monorepo's own lint setup is unchanged; it stays on ESLint 8 and .eslintrc.js.

Known upstream issue: ESLint's built-in no-unused-vars crashes on some Flow declare class declarations in ESLint 9 and 10, with both flow-eslint and hermes-eslint. The bug is in ESLint itself, not this config.

Changelog:

[GENERAL] [ADDED] - @react-native/eslint-config: support ESLint 10; the flat config now parses JavaScript with flow-eslint

Test Plan:

Repo checks, still on ESLint 8:

yarn lint                  # passes, --max-warnings 0
yarn test packages/eslint-config-react-native packages/eslint-plugin-react-native packages/eslint-plugin-specs private/eslint-plugin-monorepo
                           # 144 passed
yarn flow-check            # Found 0 errors
yarn format-check-javascript   # All matched files use Prettier code style!

The prettier config test now also checks every block in flat.js, so no block re-enables a rule that eslint-config-prettier turns off.

Consumer smoke test: I ran npm pack on @react-native/eslint-config and @react-native/eslint-plugin, installed them into a sample app via overrides, and linted .js (Flow + JSX), .tsx, .ts and __tests__ files:

  • ESLint 10.12.0, flat config: no crashes. Reports no-unused-vars, @react-native/no-deep-imports, react-native/no-inline-styles, @typescript-eslint/no-unused-vars and @typescript-eslint/no-shadow.
  • ESLint 9.39.5, flat config: exactly the same results as ESLint 10.
  • ESLint 8.57.1, legacy .eslintrc config: works as before. The one @flow file fails with Cannot read properties of undefined (reading 'forEach'), and so does unchanged main with @react-native/babel-preset 0.84, so this PR doesn't cause it.
  • @react-native/eslint-plugin-specs on ESLint 10: react-native-modules reports an invalid NativeSeeded.js spec ('AnyTypeAnnotation' is unsupported in NativeModule specs) instead of throwing.

@meta-cla

meta-cla Bot commented Oct 14, 2026

Copy link
Copy Markdown

Hi @usama-liaqat!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla

meta-cla Bot commented Oct 14, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 14, 2026
@meta-cla

meta-cla Bot commented Oct 14, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 14, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant