1.2.1 • Published 5 months ago

@wogns3623/eslint-plugin-better-exhaustive-deps v1.2.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

Better react exhaustive-deps eslint plugin with static variable check

Installation

yarn add -D @wogns3623/eslint-plugin-better-exhaustive-deps
# or
pnpm i -D @wogns3623/eslint-plugin-better-exhaustive-deps
# or
npm i -D @wogns3623/eslint-plugin-better-exhaustive-deps

Usage

For ESLint 9.0.0 and above users, add the recommended-latest config.

import betterHooks from "@wogns3623/eslint-plugin-better-exhaustive-deps";

module.exports = [
  // ...
  betterHooks.configs["recommended-latest"],
];

Legacy Config (.eslintrc)

If you are still using ESLint below 9.0.0, please continue to use recommended-legacy. To avoid breaking changes, we still support recommended as well, but note that this will be changed to alias the flat recommended config in v6.

{
  "extends": [
    // ...
    "plugin:@wogns3623/better-exhaustive-deps/recommended-legacy"
  ]
}

Custom Configuration

To use this plugin, you must disable original react-hooks/exhaustive-deps rule

import reactHooks from "eslint-plugin-react-hooks";
import betterHooks from "@wogns3623/eslint-plugin-better-exhaustive-deps";

export default [
  {
    files: ["**/*.{js,jsx}"],
    plugins: {
      "react-hooks": reactHooks,
      "@wogns3623/better-exhaustive-deps": betterHooks,
    },
    // ...
    rules: {
      // disable original rule
      "react-hooks/exhaustive-deps": "off",
      "@wogns3623/better-exhaustive-deps/exhaustive-deps": "warn",
    },
  },
];

Legacy Config (.eslintrc)

module.exports = {
  plugins: [
    // ...
    "@wogns3623/better-exhaustive-deps",
  ],
  rules: {
    // disable original rule
    "react-hooks/exhaustive-deps": "off",
    "@wogns3623/better-exhaustive-deps/exhaustive-deps": "warn",
  },
};

Advanced Configuration

checkMemoizedVariableIsStatic

Check variable memoized by useCallback or useMemo is static.

If Deps is empty or filled with static variable, the return value is also treated as a static variable.

module.exports = {
  // ...
  rules: {
    // disable original rule
    "react-hooks/exhaustive-deps": "off",
    "@wogns3623/better-exhaustive-deps/exhaustive-deps": [
      "warn",
      {
        checkMemoizedVariableIsStatic: true,
      },
    ],
  },
  // ...
};

staticHooks

Return values ​​registered as true are treated as static variable.

Can configure destructured value independently.

module.exports = {
  // ...
  rules: {
    // disable original rule
    "react-hooks/exhaustive-deps": "off",
    "@wogns3623/better-exhaustive-deps/exhaustive-deps": [
      "warn",
      {
        staticHooks: {
          useCustomRef: true,
          useSomething: [false, true],
          useSomethingOther: {
            value: false,
            callback: true,
          },
        },
      },
    ],
  },
  // ...
};

use grncdr's code https://github.com/facebook/react/issues/16873#issuecomment-536346885

TODO

  • Check callback generated by useCallback is immutable
  • Create a rule to check for unnecessary static (stable) values in dependency list.
  • Add presets for popular React libraries
  • Add automatic inference for whether a custom hook return value is static or not
  • Update test code for checkMemoizedVariableIsStatic
  • Add test code for staticHooks