-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Allow useEffect(fn, undefined)
in react-hooks/exhaustive-deps
.
#27525
Conversation
Comparing: 309c8ad...329f4d2 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: Expand to show
|
@davidaurelio pointed out to me that However, (() => {
// Shadowing of global property 'undefined'. eslint(no-shadow-restricted-names)
const undefined = 'banana';
}) The majority of people are using the recommended rules so I believe it is reasonable to assume that people who use a linter do not name their local dependency array variables |
Sorry, but Undefined as dependency sounds wrong on so many levels. |
Whether it sounds wrong to you or not is irrelevant to this discussion. The facts are that React supports this pattern, there are valid use cases, it is encoded in the TypeScript/Flow types, and this eslint plugin already considers omitting the dependency argument altogether as correct. |
This makes sense to me to allow in this linter. You can always have an additional linter that disallows or forces undefined if you have strong feelings about that either way. |
…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. DiffTrain build for [d947c2f](d947c2f)
- facebook/react#27641 - facebook/react#27661 - facebook/react#27640 - facebook/react#27595 - facebook/react#27600 - facebook/react#27598 - facebook/react#27590 - facebook/react#27606 - facebook/react#27608 - facebook/react#27601 - facebook/react#27616 - facebook/react#27615 - facebook/react#27614 - facebook/react#27599 - facebook/react#27597 - facebook/react#27525 - facebook/react#27571
Updates React from 08a39539f to 2983249dd. ### React upstream changes - facebook/react#27641 - facebook/react#27661 - facebook/react#27640 - facebook/react#27595 - facebook/react#27600 - facebook/react#27598 - facebook/react#27590 - facebook/react#27606 - facebook/react#27608 - facebook/react#27601 - facebook/react#27616 - facebook/react#27615 - facebook/react#27614 - facebook/react#27599 - facebook/react#27597 - facebook/react#27525 - facebook/react#27571 Updates @types/react to 18.2.37 Updates @types/react-dom to 18.2.15
…acebook#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.
…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. DiffTrain build for commit d947c2f.
##### [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))
What is the point of using useEffect with undefined then?
It's looks weird. In such cases developers need to have lint warning and think about it. And finally rewrite it as:
Do you know other samples that you need undefined? Would be great to see it! |
These run in entirely different contexts during hybrid render, the former runs only in browser while the latter will log both on the server and the browser. |
@cpojer Where can I find your custom rule? 🙂 |
Ah, I never shared it. Here you go: https://gist.github.com/cpojer/92a9cb355553011394ff4bc975b93bad |
Summary
There is a bug in the
react-hooks/exhaustive-deps
rule that forbids the dependencies argument from beingundefined
. 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:
useEffect
calls etc.) is a valid use case for hooks that should re-run on every render.exhaustive-deps
rule already.undefined
because hooks are typed asuseEffect(effect: EffectCallback, deps?: DependencyList): void;
.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 explicitundefined
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?
yarn test ESLintRuleExhaustiveDeps-test