Files
react/packages/eslint-plugin-react-hooks
Christoph Nakazawa d947c2f110 Allow useEffect(fn, undefined) in react-hooks/exhaustive-deps. (#27525)
## Summary

There is a bug in the `react-hooks/exhaustive-deps` rule that forbids
the dependencies argument from being `undefined`. It triggers the error
that the dependency list is not an array literal. This makes sense in
pre ES5 strict-mode environments as undefined could be redefined, but
should not be a concern in today's JS environments.

**Justification:**
* The deps argument being undefined (for `useEffect` calls etc.) is a
valid use case for hooks that should re-run on every render.
* The deps argument being omitted is considered a valid use case by the
`exhaustive-deps` rule already.
* The TypeScript type definitions support passing `undefined` because
hooks are typed as `useEffect(effect: EffectCallback, deps?:
DependencyList): void;`.
* Since omitting an argument and passing `undefined` are considered
equivalent, this eslint rule should consider them as equivalent too.

Further, I accidentally forgot passing a dependency array to `useEffect`
in code that I shared on Twitter, and people started abusing me about
it. I'd like to create an eslint rule for my projects that requires me
to provide a dep argument in all cases (`undefined`, `[]` or the list of
dependencies) so that I can avoid such problems in the future. This
would also force me to always think about the dependencies instead of
accidentally forgetting them and my hook running on each render. In an
audit of my own codebase I had about 3% of hooks that I want to run on
each render, and adding an explicit `undefined` seems reasonable in
those situations.

It could be argued this could be an option or part of the
`exhaustive-deps` rule, but it's probably better to merge this PR, make
a release and see if my custom eslint rule gains traction in the future.

## How did you test this change?

* Added a test.
* `yarn test ESLintRuleExhaustiveDeps-test`
* Careful code inspection.
2023-11-01 15:05:55 -04:00
..
2018-10-29 11:26:54 -07:00

eslint-plugin-react-hooks

This ESLint plugin enforces the Rules of Hooks.

It is a part of the Hooks API for React.

Installation

Note: If you're using Create React App, please use react-scripts >= 3 instead of adding it directly.

Assuming you already have ESLint installed, run:

# npm
npm install eslint-plugin-react-hooks --save-dev

# yarn
yarn add eslint-plugin-react-hooks --dev

Then extend the recommended eslint config:

{
  "extends": [
    // ...
    "plugin:react-hooks/recommended"
  ]
}

Custom Configuration

If you want more fine-grained configuration, you can instead add a snippet like this to your ESLint configuration file:

{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}

Advanced Configuration

exhaustive-deps can be configured to validate dependencies of custom Hooks with the additionalHooks option. This option accepts a regex to match the names of custom Hooks that have dependencies.

{
  "rules": {
    // ...
    "react-hooks/exhaustive-deps": ["warn", {
      "additionalHooks": "(useMyCustomHook|useMyOtherCustomHook)"
    }]
  }
}

We suggest to use this option very sparingly, if at all. Generally saying, we recommend most custom Hooks to not use the dependencies argument, and instead provide a higher-level API that is more focused around a specific use case.

Valid and Invalid Examples

Please refer to the Rules of Hooks documentation and the Hooks FAQ to learn more about this rule.

License

MIT