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 & "Flat Config" (ESLint 9) #28313

Open
Tracked by #18093 ...
JoshuaKGoldberg opened this issue Feb 13, 2024 · 77 comments · May be fixed by #30774
Open
Tracked by #18093 ...

eslint-plugin-react-hooks & "Flat Config" (ESLint 9) #28313

JoshuaKGoldberg opened this issue Feb 13, 2024 · 77 comments · May be fixed by #30774

Comments

@JoshuaKGoldberg
Copy link

JoshuaKGoldberg commented Feb 13, 2024

👋 Coming over from eslint/eslint#18093: ESLint is migrating to a new "flat config" format that will be the default in ESLint v9.

It doesn't look like eslint-plugin-react-hooks has documented support yet. But, based on searching around (e.g. vercel/next.js#49337), ESLint v9 is basically supported if you wire it up manually in your config:

// eslint.config.js
import eslint from "@eslint/js";
import hooksPlugin from "eslint-plugin-react-hooks";

export default [
  eslint.configs.recommended,
  {
    plugins: {
      "react-hooks": hooksPlugin,
    },
    rules: hooksPlugin.configs.recommended.rules,
  },
];

Most community plugins provide a more convenient wrapper. For example, eslint-plugin-jsdoc provides a jsdoc.configs['flat/recommended'] object:

// eslint.config.js
import jsdoc from 'eslint-plugin-jsdoc';

export default [
  jsdoc.configs['flat/recommended'],
];

Would the React team be open to a PR adding in a preset object like that? And either way, updating the docs on https://www.npmjs.com/package/eslint-plugin-react-hooks?

Note: this was also filed as reactjs/react.dev#6430.

I'm posting this issue here as a reference & cross-linking it to the table in eslint/eslint#18093. If there's anything technical blocking the extension from working with flat configs, please let us know - we'd be happy to try to help! 💜

Additional resources:

(sorry for not using the issue templates - I wasn't sure whether this would count as a bug)

@eps1lon
Copy link
Collaborator

eps1lon commented Feb 13, 2024

Thank you for reaching out. What would be involved in creating such a wrapper? Does it make more sense to file a PR and then see how it'll look?

We're only on ESLint 7 though so I guess we need to upgrade that first to test.

@JoshuaKGoldberg
Copy link
Author

What would be involved in creating such a wrapper?

It's not too much work (famous last words, I know). In theory the plugin should be able to get away with exporting an object containing configs, meta, and rules. https://eslint.org/docs/latest/extend/plugin-migration-flat-config#adding-plugin-meta-information shows a very minimal object.

make more sense to file a PR and then see how it'll look?

👍

We're only on ESLint 7 though so I guess we need to upgrade that first to test.

Yeah it feels like it'd probably be cleanest to upgrade to ESLint 8 first, just in case any breaking changes impact the plugin.

@RoystonS
Copy link

RoystonS commented Apr 5, 2024

Note that even wiring up the plugin manually doesn't enable it to work with the now-released ESLint 9: the plugin currently uses APIs like context.getSource which don't exist any more (eslint/eslint#17520), so there'll need to be some upgrade work.

e.g.

`${context.getSource(reactiveHook)} will be lost after each ` +

@JstnMcBrd
Copy link

Eslint officially released v9.0.0 today. However, the eslint-plugin-react-hooks plugin still restricts eslint to v8 in the peerDependencies list, so nobody who uses the plugin can download v9 without breaking dependency resolution.

Hope you'll add support for v9 soon!

@RoystonS
Copy link

RoystonS commented Apr 6, 2024

Should we raise a separate issue for v9 API support?

@yhx-12243
Copy link

yhx-12243 commented Apr 6, 2024

Should we raise a separate issue for v9 API support?

Currently under discussion in jsx-eslint/eslint-plugin-react#3699.

@eps1lon
Copy link
Collaborator

eps1lon commented Apr 6, 2024

ESLint v9 support will be done in #28773

@josiahgallen
Copy link

@eps1lon how far away from merge/release is this update to support eslint v9?

@virtuallyunknown
Copy link

ESLint v9 support will be done in #28773

Hey @eps1lon, greetings!

I just wanted to ask, is #28773 part of the 4.6.0 release that was published on npm 3 days ago or it's planned for a future release?

I am currently in the process of migrating to flat config, and the plugin is giving me an error.

Oops! Something went wrong! :(

ESLint: 9.1.0

TypeError: context.getSource is not a function
Occurred while linting /home/user/projects/eslint-flat-config-migration/src/index.tsx:8
Rule: "react-hooks/exhaustive-deps"
    at visitFunctionWithDependencies (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@9.1.0/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js:1704:42)
    at visitCallExpression (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@9.1.0/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js:1759:11)
    at ruleErrorHandler (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/linter.js:1115:48)
    at /home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:297:26)
    at NodeEventGenerator.applySelectors (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:326:22)
    at NodeEventGenerator.enterNode (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:340:14)
    at runRules (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/linter.js:1154:40)

If needed, here is a my repository where the issue can be reproduced by running npx eslint src/index.tsx

https://github.com/virtuallyunknown/eslint-flat-config-migration

Relevant files:
https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/eslint.config.js
https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/configs/react.js

Cheers!

@JacobZyy
Copy link

ESLint v9 support will be done in #28773

Hey @eps1lon, greetings!

I just wanted to ask, is #28773 part of the 4.6.0 release that was published on npm 3 days ago or it's planned for a future release?

I am currently in the process of migrating to flat config, and the plugin is giving me an error.

Oops! Something went wrong! :(

ESLint: 9.1.0

TypeError: context.getSource is not a function
Occurred while linting /home/user/projects/eslint-flat-config-migration/src/index.tsx:8
Rule: "react-hooks/exhaustive-deps"
    at visitFunctionWithDependencies (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@9.1.0/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js:1704:42)
    at visitCallExpression (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint-plugin-react-hooks@4.6.0_eslint@9.1.0/node_modules/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js:1759:11)
    at ruleErrorHandler (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/linter.js:1115:48)
    at /home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/safe-emitter.js:45:58
    at Array.forEach (<anonymous>)
    at Object.emit (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:297:26)
    at NodeEventGenerator.applySelectors (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:326:22)
    at NodeEventGenerator.enterNode (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/node-event-generator.js:340:14)
    at runRules (/home/user/projects/eslint-flat-config-migration/node_modules/.pnpm/eslint@9.1.0/node_modules/eslint/lib/linter/linter.js:1154:40)

If needed, here is a my repository where the issue can be reproduced by running npx eslint src/index.tsx

https://github.com/virtuallyunknown/eslint-flat-config-migration

Relevant files: https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/eslint.config.js https://github.com/virtuallyunknown/eslint-flat-config-migration/blob/master/configs/react.js

Cheers!

got the same error and I turn off the rules about react-hooks...

@smaven
Copy link

smaven commented Apr 25, 2024

The issue seems to have been resolved in the canary release.

If you are using eslint-plugin-react, some rules such as react/display-name or other recommended ones don't work: jsx-eslint/eslint-plugin-react#3699.

@eps1lon
Copy link
Collaborator

eps1lon commented Apr 25, 2024

If you are using eslint-plugin-react

eslint-plugin-react is not authored by the React team. Please file an issue for this plugin in https://github.com/jsx-eslint/eslint-plugin-react instead.

ESLint v9 support is available in the Canary release channel (earliest version 5.1.0-canary-cb151849e1-20240424) and will be released as stable with the stable release of React 19.

@virtuallyunknown
Copy link

virtuallyunknown commented Apr 25, 2024

I am not sure if this feedback is of any value, but it looks like the types from eslint and typescript-eslint are signaling about potential issues.

// @ts-check

// @typescript-eslint/utils: 7.7.1
// eslint-plugin-react-hooks: 5.1.0-canary-cb151849e1-20240424

import eslintPluginReactHooks from 'eslint-plugin-react-hooks';

/** @type {import('eslint').Linter.FlatConfig[]} */
export const configuration1 = [
    {
        plugins: {
            'react-hooks': eslintPluginReactHooks
        }
    }
];

/** @type {import('@typescript-eslint/utils').TSESLint.FlatConfig.ConfigFile} */
export const configuration2 = [
    {
        plugins: {
            'react-hooks': eslintPluginReactHooks
        }
    }
];

I don't want to paste the error message because it's a giant wall of text, but feel free to try it on your own.

This appears to be a type error only, and as far as I can tell the plugin is working as expected, so thanks for the updates, much appreciated!

@pauliesnug
Copy link

Still having issues with @rc version. Any workaround?
image

Plugins: Property '"rules-of-hooks"' is incompatible with index signature.

Rules: The expected type comes from property 'rules' which is declared here on type 'ConfigWithExtends'

@nikischin You could try removing and/or updating any sort of @types/eslint-plugin-react-hooks you have installed. Otherwise it's an issue with the built-in types, which you can really only fix by overriding the global types with a d.ts file.

@OmniSliver
Copy link

Still having issues with @rc version. Any workaround?
...
Plugins: Property '"rules-of-hooks"' is incompatible with index signature.

You forgot the .rules after the .recommended in ...reactHooks.configs.recommended.rules

@nikitastryuk
Copy link

nikitastryuk commented Sep 24, 2024

@OmniSliver Thanks!

But after this fix TS still complains:
image

@nikitaNaredi
Copy link

nikitaNaredi commented Sep 27, 2024

My app is in CRA JS and am trying to migrate from .eslintrc to eslint.config.mjs by using the migrator. Now when am trying to build the project am getting:

Definition for rule 'react-hooks/exhaustive-deps' was not found react-hooks/exhaustive-deps.
Please help.

This is my eslint.config.mjs file after migration:

import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
import jsxA11Y from "eslint-plugin-jsx-a11y";
import reactHooks from "eslint-plugin-react-hooks";
import prettier from "eslint-plugin-prettier";
import react from "eslint-plugin-react";
import babelParser from "@babel/eslint-parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
    baseDirectory: __dirname,
    recommendedConfig: js.configs.recommended,
    allConfig: js.configs.all,
});

export default [
    {
        ignores: [
            "src/registerServiceWorker.js",
          ],
    },
    ...fixupConfigRules(
        compat.extends(
            "airbnb",
            "plugin:jsx-a11y/recommended",
            "prettier",
            "plugin:prettier/recommended",
            "react-app",
            "eslint:recommended",
            "plugin:react/recommended",
            "plugin:react-hooks/recommended"
        )
    ),
    {
        plugins: {
            "jsx-a11y": fixupPluginRules(jsxA11Y),
            "react-hooks": fixupPluginRules(reactHooks),
            prettier: fixupPluginRules(prettier),
            react: fixupPluginRules(react),
        },

        languageOptions: {
            parser: babelParser,
            ecmaVersion: 2023,
            sourceType: "module",

            parserOptions: {
                ecmaFeatures: {
                    jsx: true,
                },

                requireConfigFile: true,
            },
        },

        rules: {
            ...reactHooks.configs.recommended.rules,
            semi: 0,
            "react/destructuring-assignment": 0,

            "react/jsx-filename-extension": [
                1,
                {
                    extensions: [".js", ".jsx"],
                },
            ],

            "react/jsx-fragments": ["off", "element"],

            "react/jsx-props-no-spreading": [
                "error",
                {
                    custom: "ignore",
                },
            ],

            "jsx-a11y/href-no-hash": "off",
            "jsx-a11y/click-events-have-key-events": 0,
            "jsx-a11y/label-has-associated-control": 0,
            "react/button-has-type": 0,
            "react/prop-types": "off",
            "default-param-last": "error",
            "no-promise-executor-return": "off",
            "react/no-unstable-nested-components": "off",

            "prettier/prettier": [
                "error",
                {
                    endOfLine: "auto",
                },
            ],

            "arrow-body-style": "off",
            "prefer-arrow-callback": "off",
            "react-hooks/rules-of-hooks": "error",
            "react-hooks/exhaustive-deps": "warn",
            "react/display-name": "off",
        },
    },
    {
        files: ["src/app/*.js"],

        rules: {
            "no-unused-expressions": "off",
            "import/no-cycle": "off",
            "no-param-reassign": "off",
        },
    },
    {
        files: [
            "src/features/**",
        ],

        rules: {
            "default-param-last": "off",
        },
    },
];

@ArthurGuez
Copy link

Has anyone tried to migrate to @eslint-react/eslint-plugin instead?
It's recommended by the e18e community and it supports flat config

@jbouder
Copy link

jbouder commented Sep 27, 2024

@eslint-react/eslint-plugin

Definitely curious to hear thoughts on this as an alternative

@Markus-ipse
Copy link

@eslint-react/eslint-plugin

Definitely curious to hear thoughts on this as an alternative

Seem like a useful ESLint plugin, but it doesn't have any hook-related rules so unfortunately it cannot really replace eslint-plugin-react-hooks.

@jbouder
Copy link

jbouder commented Sep 27, 2024

@eslint-react/eslint-plugin

Definitely curious to hear thoughts on this as an alternative

Seem like a useful ESLint plugin, but it doesn't have any hook-related rules so unfortunately it cannot really replace eslint-plugin-react-hooks.

Looks like you’re correct. There are some hook rules here, but not sure they’re adequate: https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-hooks-extra

@ChromeQ
Copy link

ChromeQ commented Sep 27, 2024

The heck is going on here? eslint-plugin-react-hooks is the 2nd most downloaded ESLint plugin in the npm ecosystem, and is maintained by one of the biggest tech companies in the world. It's been 6 months since ESLint 9 was released and this package is still out of date. I can see the support is merged so can't we just get a release?

ESLint v9 has been available for some time now and it is unclear when React 19 will be released. Can the dev team please consider releasing just this the eslint-plugin-react-hooks package (with ESLint v9 support) to unblock the dependency chain?

These are the most sensible replies on the thread and worth a re-quote. It's insane that this is not released yet despite being fixed and all other popular plugins are supported (this is the last one not compatible on my stack) and being held back for no good reason, except waiting for react v19 which has no timeline and expected known release date. They should not be linked and we should get a release for flat-config compatible plugin separated from react 19 compatibility.

LET'S GET A RELEASE!!!

@elliottAtTreatment
Copy link

The heck is going on here? eslint-plugin-react-hooks is the 2nd most downloaded ESLint plugin in the npm ecosystem, and is maintained by one of the biggest tech companies in the world. It's been 6 months since ESLint 9 was released and this package is still out of date. I can see the support is merged so can't we just get a release?

ESLint v9 has been available for some time now and it is unclear when React 19 will be released. Can the dev team please consider releasing just this the eslint-plugin-react-hooks package (with ESLint v9 support) to unblock the dependency chain?

These are the most sensible replies on the thread and worth a re-quote. It's insane that this is not released yet despite being fixed and all other popular plugins are supported (this is the last one not compatible on my stack) and being held back for no good reason, except waiting for react v19 which has no timeline and expected known release date. They should not be linked and we should get a release for flat-config compatible plugin separated from react 19 compatibility.

LET'S GET A RELEASE!!!

Just wait. Use the beta release. It's a super easy fix. Get subscribed and read your emails. Update it back to stable version when it's released. The company is a titan with red tape and QA procedures that must be followed. Complaining here for an earlier full release will do nothing but spam our emails.

@ChromeQ
Copy link

ChromeQ commented Sep 27, 2024

Just wait.

I have been, so have all of us, for far too long, that's the general consensus here as eslint v9 has been out more than 7 months now.

Use the beta release. It's a super easy fix.

Not always an easy fix for enterprise and corporations who rely on stability of versions so beta is too risky, or even people who start a new project and automatically get the latest version of a basic dependency like eslint to find the most popular plugins aren't supported yet.

Get subscribed and read your emails.

I have been, so have all of us, for far too long, that's the general consensus here as eslint v9 has been out more than 7 months now.

Update it back to stable version when it's released.

Not always an easy fix for enterprise and corporations who rely on stability of versions so beta is too risky, or even people who start a new project and automatically get the latest version of a basic dependency like eslint to find the most popular plugins aren't supported yet.

The company is a titan with red tape and QA procedures that must be followed.

Fair, but QA procedures have been passed to get to be merged. The general consensus of this thread (and others) is that this is taking a bit too long for something which is already fixed. React was the "titan company" attempting to be more open source and responsive (and up until now my experience was that they were succeeding in that)

Complaining here for an earlier full release will do nothing but spam our emails

You are welcome to unsubscribe to the email updates just as I was advised to "Get subscribed and read your emails"

@OmniSliver
Copy link

If you don't want to use the beta version, you can also override the dependency in package.json and use the compatibility utilities to use the flat config.

E.g.:

  • In package.json:
    "overrides": {
      "eslint-plugin-react-hooks": {
        "eslint": "$eslint"
      }
    }
    

E.g.

  • In eslint.config.js:
    const { fixupPluginRules } = require('@eslint/compat')
    const hooksPlugin = require('eslint-plugin-react-hooks')
    ...
    
    module.exports = [
      ...
      {
        plugins: {
          'react-hooks': fixupPluginRules(hooksPlugin),
        },
        rules: hooksPlugin.configs.recommended.rules,
      }
    ]
    

@ChromeQ
Copy link

ChromeQ commented Sep 27, 2024

Thanks @OmniSliver, I know there are workarounds but I think the point here is that we shouldn't be scouring through an 8 month old issue with over 100 replies to find a workaround, especially when the fix is merged to main branch and ready to use (except it isn't released which is probably built into a single command line script for the project maintainers)

My argument stands though, enterprises and corporations have little to zero appetite for workarounds for non-stable releases, the fact that the "fix" is called fixupPluginRules suggests that these plugins need a "fix", which is unacceptable from one of the world's biggest tech companies, who are in charge of arguably the most popular front-end framework in the world and the 2nd most downloaded ESLint plugin in the npm ecosystem.

@mike-marcacci
Copy link

@ChromeQ while I generally agree with your sentiment... this is a linter.

Do your policies really prevent you from running the release candidate of a development dependency that doesn't even play a role in building your final artifacts?

I've spent a non-trivial amount of time designing and defending secure development practices, and I don't think that would be a practicable stance.

Along with everybody here, I really wish this had moved forward faster... but let's not exaggerate the inconvenience.

@jonaldinger
Copy link

For the new folks arriving here like me, here is my understanding of the current state of the world after spending way too much time digging through this thread:

  • eslint-plugin-react-hooks v4 is still incompatible with eslint v9
  • The issue has been resolved, but is not yet released
  • The simplest solution is to use the v5 release candidate of eslint-plugin-react-hooks until the actual release is available (not happening until React v19 is released). The instructions for this solution from @slk333 are now in a hidden comment (too many comments on the thread) - see it here: eslint-plugin-react-hooks & "Flat Config" (ESLint 9) #28313 (comment)
  • If you are for some reason averse to/restricted from using a beta/RC version for a developer tooling plugin, there are other solutions in this thread to manually patch the v4 plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.