Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eslint-plugin-react-hooks: Add support for ESLint v9 #28773

Merged
merged 6 commits into from
Apr 23, 2024

Conversation

eps1lon
Copy link
Collaborator

@eps1lon eps1lon commented Apr 6, 2024

Based on #28774

Does not add support for flat configs i.e. does not adress #28313.

The PR only adds support for ESLint v9 with the old config format and sets up testing infra for separate ESLint versions. The only breaking changes that affected the plugin was around removal of context.getScope and context.getSource which have simple replacements in V9 so that we don't have to fork too much to be able to support ESLint V9 and earlier.

The last commit makes it so that we have no breaking changes. If we decide to drop support for ESLint < 9.x, we can just revert 80e7b49 (#28773)

Alternate to #28772

@react-sizebot
Copy link

react-sizebot commented Apr 6, 2024

Comparing: 699d03c...c1f1de3

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 497.71 kB 497.71 kB = 88.93 kB 88.93 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 504.00 kB 504.00 kB = 89.95 kB 89.95 kB
facebook-www/ReactDOM-prod.classic.js = 591.14 kB 591.14 kB = 103.91 kB 103.91 kB
facebook-www/ReactDOM-prod.modern.js = 566.95 kB 566.95 kB = 100.12 kB 100.12 kB
test_utils/ReactAllWarnings.js Deleted 64.80 kB 0.00 kB Deleted 16.14 kB 0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.js +1.19% 76.83 kB 77.75 kB +0.90% 14.07 kB 14.20 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.js +1.19% 76.83 kB 77.75 kB +0.90% 14.07 kB 14.20 kB
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.production.js +1.16% 78.69 kB 79.60 kB +0.94% 14.31 kB 14.45 kB
oss-stable-semver/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +1.01% 93.66 kB 94.60 kB +0.61% 21.96 kB 22.09 kB
oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +1.01% 93.66 kB 94.60 kB +0.61% 21.96 kB 22.09 kB
oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js +1.00% 93.81 kB 94.75 kB +0.61% 21.98 kB 22.12 kB
test_utils/ReactAllWarnings.js Deleted 64.80 kB 0.00 kB Deleted 16.14 kB 0.00 kB

Generated by 🚫 dangerJS against c1f1de3

@eps1lon eps1lon force-pushed the rules-of-hooks-eslint-v9 branch 2 times, most recently from 43a0927 to 1a217e9 Compare April 6, 2024 16:59
@eps1lon eps1lon marked this pull request as ready for review April 7, 2024 07:50
return context.sourceCode.getScope(node);
}
}

const scopeManager = context.getSourceCode().scopeManager;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context-methods-becoming-properties
I noticed that this context.getSourceCode() was replaced with context.sourceCode, you might want to confirm that.

const sourceCode = context.sourceCode ?? context.getSourceCode();
const scopeManager = sourceCode.scopeManager;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSourceCode was only deprecated.

yarn.lock Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe split this out into a separate PR?

Copy link
Collaborator Author

@eps1lon eps1lon Apr 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It kind of doesn't make sense for these change to stay if we revert ESlint v9 support. And if we need to revert the lockfile changes, we also need to revert ESLint v9 support.

Merge conflicts in yarn.lock are not an issue since you'd just run yarn. Yarn automatically resolves merge conflicts.

I rebased this PR to isolate these changes so if we do need to bisect later, we can still do it on this branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah right, sorry I missed that there was a package.json update

@eps1lon eps1lon mentioned this pull request Apr 22, 2024
@eps1lon eps1lon merged commit 6f18664 into facebook:main Apr 23, 2024
38 checks passed
@ArnaudBarre
Copy link

ArnaudBarre commented Jul 21, 2024

@eps1lon Can we have a stable release of the eslint plugin without waiting for React 19?
With plugin-react now supporting ESLint 9, it would be great to ship vitejs/vite#12860 to new Vite users without using compat layer or a canary version.

@RomkeSandwave
Copy link

Any updates? Still waiting on this for our stack's ESLint 9 upgrade.

@lllapland
Copy link

So how to config/use it?

yarn add [email protected] -D

@rburgst
Copy link

rburgst commented Sep 13, 2024

when can we expect a release?

@xuhdev
Copy link

xuhdev commented Sep 30, 2024

Looks like we can install 5.1.0-beta-26f2496093-20240514 for now...

@c10b10
Copy link

c10b10 commented Oct 1, 2024

For who made this work:

I'm using the rc version of 5.1.0, but still getting the same error. This is my config:

import { fixupConfigRules } from "@eslint/compat";
import eslint from "@eslint/js";
import eslintImportX from "eslint-plugin-import-x";
// import eslintPluginReactHooks from "eslint-plugin-react-hooks";
import eslintReactJsxRuntime from "eslint-plugin-react/configs/jsx-runtime.js";
import eslintReactRecommended from "eslint-plugin-react/configs/recommended.js";
import globals from "globals";
import tsEslint from "typescript-eslint";
 
const typescriptReactApp = [
  { languageOptions: { globals: globals.browser } },
  eslint.configs.recommended,
  ...tsEslint.configs.recommended,
  eslintPluginReactHooks,
  ...fixupConfigRules(eslintReactRecommended),
  ...fixupConfigRules(eslintReactJsxRuntime),
  {
    rules: {
      "react/prop-types": "off",
    },
    files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]
  },
];

Am I doing something wrong?

@EmilYanbaev
Copy link

EmilYanbaev commented Oct 4, 2024

@c10b10 My working config
"eslint-plugin-react-hooks": "5.1.0-beta-26f2496093-20240514"

import globals from 'globals'
import pluginJs from '@eslint/js'
import tseslint from 'typescript-eslint'
import pluginReact from 'eslint-plugin-react'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import pluginJest from 'eslint-plugin-jest'
import pluginReactHooks from 'eslint-plugin-react-hooks'

export default [
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  pluginReact.configs.flat.recommended,
  pluginJest.configs['flat/recommended'],
  eslintPluginPrettierRecommended,
  {
    files: ['src/**/*.{js,ts,jsx,tsx}'],
    plugins: {
      'react-hooks': pluginReactHooks
    },
    rules: {
      'react/react-in-jsx-scope': 'off',
      'react/prop-types': 'off',
      ...pluginReactHooks.configs.recommended.rules
    }
  },
  {
    ignores: ['dist/*']
  }
]

renovate bot added a commit to mmkal/eslint-plugin-mmkal that referenced this pull request Oct 11, 2024
##### [v5.0.0](https://github.com/facebook/react/blob/HEAD/packages/eslint-plugin-react-hooks/CHANGELOG.md#500)

-   **New Violations:** Component names now need to start with an uppercase letter instead of a non-lowercase letter. This means `_Button` or `_component` are no longer valid. ([@kassens](https://github.com/kassens)) in [#25162](facebook/react#25162)

<!---->

-   Consider dispatch from `useActionState` stable. ([@eps1lon](https://github.com/eps1lon) in [#29665](facebook/react#29665))
-   Add support for ESLint v9. ([@eps1lon](https://github.com/eps1lon) in [#28773](facebook/react#28773))
-   Accept `as` expression in callback. ([@StyleShit](https://github.com/StyleShit) in [#28202](facebook/react#28202))
-   Accept `as` expressions in deps array. ([@StyleShit](https://github.com/StyleShit) in [#28189](facebook/react#28189))
-   Treat `React.use()` the same as `use()`. ([@kassens](https://github.com/kassens) in [#27769](facebook/react#27769))
-   Move `use()` lint to non-experimental. ([@kassens](https://github.com/kassens) in [#27768](facebook/react#27768))
-   Support Flow `as` expressions. ([@cpojer](https://github.com/cpojer) in [#27590](facebook/react#27590))
-   Allow `useEffect(fn, undefined)`. ([@kassens](https://github.com/kassens) in [#27525](facebook/react#27525))
-   Disallow hooks in async functions. ([@acdlite](https://github.com/acdlite) in [#27045](facebook/react#27045))
-   Rename experimental `useEvent` to `useEffectEvent`. ([@sebmarkbage](https://github.com/sebmarkbage) in [#25881](facebook/react#25881))
-   Lint for presence of `useEvent` functions in dependency lists. ([@poteto](https://github.com/poteto) in [#25512](facebook/react#25512))
-   Check `useEvent` references instead. ([@poteto](https://github.com/poteto) in [#25319](facebook/react#25319))
-   Update `RulesOfHooks` with `useEvent` rules. ([@poteto](https://github.com/poteto) in [#25285](facebook/react#25285))
devjiwonchoi added a commit to vercel/next.js that referenced this pull request Oct 14, 2024
> [!WARNING]
> **Breaking Change:** Now uses `[email protected]` which
has a new violation disallowing Component names starting with anything
but an uppercase letter. See
https://github.com/facebook/react/releases/tag/eslint-plugin-react-hooks%405.0.0
for more details.

Adds support of ESLint v9 to `eslint-plugin-next`, `eslint-config-next`
and `next lint`.

Does not require using the new flat config format. `next lint` will
automatically ensure the old config format can be used.

### Why?

As `eslint-plugin-react-hooks` has been updated for ESLint v9 support
and is a helpful package for Next v15 upgrade, unblock the restrictions
to upgrade to ESLint v9.

Also, ESLint v8 is [End of
Life](https://eslint.org/blog/2024/09/eslint-v8-eol-version-support/#:~:text=ESLint%20v8.-,x%20end%20of%20life%20is%20October%205%2C%202024,x%20on%20October%205%2C%202024.)
support since Oct 5th, so is good to unblock v9 now.

Plugins bumped:
- [x]
[@rushstack/eslint-patch](microsoft/rushstack#4719)
([v1.10.3](https://www.npmjs.com/package/@rushstack/eslint-patch/v/1.10.3?activeTab=versions)
no release post, confirmed on NPM)
- [x]
[@typescript-eslint/eslint-plugin](typescript-eslint/typescript-eslint#9002)
([v8.0.0](typescript-eslint/typescript-eslint#9002 (comment)))
- [x]
[eslint-plugin-import](import-js/eslint-plugin-import#2996)
([v2.31.0](https://github.com/import-js/eslint-plugin-import/releases/tag/v2.31.0))
- [x]
[eslint-plugin-jsx-a11y](jsx-eslint/eslint-plugin-jsx-a11y#1009)
([v6.10.0](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/releases/tag/v6.10.0))
- [x]
[eslint-plugin-react](jsx-eslint/eslint-plugin-react#3759)
([v7.35.0](https://github.com/jsx-eslint/eslint-plugin-react/releases/tag/v7.35.0))
- [x]
[eslint-plugin-react-hooks](facebook/react#28773)
([v5.0.0](https://github.com/facebook/react/releases/tag/eslint-plugin-react-hooks%405.0.0))

We have to switch to ESLint v9 in our repo due to a pnpm bug where it
automatically uses ESLint v9 even though we only installed it via
`eslint-v9: npm:[email protected]`. This is a pnpm bug that wouldn't happen
with Yarn v1, v4 nor NPM.

Closes #64409
Closes #64114
Closes #64453

Closes NEXT-3293

---------

Co-authored-by: Sebastian "Sebbie" Silbermann <[email protected]>
7259324177

This comment was marked as spam.

@eps1lon
Copy link
Collaborator Author

eps1lon commented Oct 16, 2024

Released in [email protected]

7259324177

This comment was marked as spam.

@facebook facebook deleted a comment from 7259324177 Oct 18, 2024
@Foxeye-Rinx
Copy link

My config for my Tanstack Start project

import pluginRouter from "@tanstack/eslint-plugin-router";
import pluginReactHooks from "eslint-plugin-react-hooks";
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
import globals from "globals";

export default [
  ...pluginRouter.configs["flat/recommended"],
  ...tseslint.configs.recommended,
  {
    files: ["**/**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
    ...pluginReact.configs.flat.recommended,
    languageOptions: {
      ...pluginReact.configs.flat.recommended.languageOptions,
      globals: {
        ...globals.serviceworker,
      },
    },
  },
  {
    files: ["**/**/*.{js,ts,jsx,tsx}"],
    plugins: {
      "react-hooks": pluginReactHooks,
    },
    rules: {
      "react/react-in-jsx-scope": "off",
      "react/prop-types": "off",
      ...pluginReactHooks.configs.recommended.rules,
    },
  },
];

ESLint version: 9.12
Node version: v20.16.0

Note that the eslint-plugin-react mentioned that:

Note: Our shareable configs does not preconfigure files or languageOptions.globals. For most of the cases, you probably want to configure some properties by yourself.

So I configure the files pattern myself.
To know if the files are detected or to troubleshoot issues:

  • use eslint config inspector
  • And npx eslint . (from my test some TypeErrors were not detected by the inspector, that's understandable because the inspector does not really run the linter)

I added some scripts to my package.json config:

"scripts": {
   ...
   "lint": "npx eslint .",
   "eslint-inspector": "npx @eslint/config-inspector@latest"
}

You need to restart the ESLint server to make the ESLint extension work after getting things done.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.