Commit Graph
107 Commits
Author SHA1 Message Date
lauren 820af20971 [eslint] Disallow use within try/catch blocks (#34040)
Follow up to #34032. The linter now ensures that `use` cannot be used
within try/catch.
2025-07-29 12:33:42 -04:00
Sebastian "Sebbie" Silbermann 19baee813c [Runtime] Fix CI (#33999) 2025-07-25 21:04:35 +02:00
Joseph Savona 7f510554ad [compiler] Cleanup diagnostic messages (#33765)
Minor sytlistic cleanup

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33765).
* #33981
* #33777
* #33767
* __->__ #33765
2025-07-24 15:45:17 -07:00
Joseph Savona 707e321f8f [compiler][wip] Improve diagnostic infra (#33751)
Work in progress, i'm experimenting with revamping our diagnostic infra.
Starting with a better format for representing errors, with an ability
to point ot multiple locations, along with better printing of errors. Of
course, Babel still controls the printing in the majority case so this
still needs more work.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33751).
* #33981
* #33777
* #33767
* #33765
* #33760
* #33759
* #33758
* __->__ #33751
* #33752
* #33753
2025-07-24 15:37:06 -07:00
Jordan Brown 97cdd5d3c3 [eslint] Do not allow useEffectEvent fns to be called in arbitrary closures (#33544)
Summary:

useEffectEvent is meant to be used specifically in combination with
useEffect, and using
the feature in arbitrary closures can lead to surprising reactivity
semantics. In order to
minimize risk in the experimental rollout, we are going to restrict its
usage to being
called directly inside an effect or another useEffectEvent, effectively
enforcing the function
coloring statically. Without an effect system this is the best we can
do.
2025-07-10 16:51:12 -04:00
Jordan Brown 99efc627a5 [eslint] Add an option to require dependencies on effect hooks (#33344)
Summary:

To prepare for automatic effect dependencies, some codebases may want to
codemod
existing useEffect calls with no deps to include an explicit undefined
second argument
in order to preserve the "run on every render" behavior. In sufficiently
large codebases,
this may require a temporary enforcement period where all effects
provide an explicit
dependencies argument.

Outside of migration, relying on a component to render can lead to real
bugs,
especially when working with memoization.
2025-05-23 10:09:41 -04:00
Jan Kassens a3abf5f2f8 [eslint-plugin-react-hooks] add experimental_autoDependenciesHooks option (#33294) 2025-05-19 15:08:30 -04:00
Jan Kassens 4448b18760 [eslint-plugin-react-hooks] fix exhaustive deps lint rule with component syntax (#33182) 2025-05-15 12:51:18 -04:00
Jan Kassens 4c4a57c4f9 [eslint-plugin-react-hooks] updates for component syntax (#33089)
Adds support for Flow's component and hook syntax.
[docs](https://flow.org/en/docs/react/component-syntax/)
2025-05-02 15:04:45 -04:00
lauren ff697fc58b [eprh] Temporarily disable ref access in render validation (#32839)
This rule currently has a few false positives, so let's disable it for
now (just in the eslint rule, it's still enabled in the compiler) while
we iterate on it.
2025-04-09 14:49:31 -04:00
michael faithandLauren Tan 5ccfcd17ff feat(eslint-plugin-react-hooks): merge rule from eslint-plugin-react-compiler into react-hooks plugin (#32416)
This change merges the `react-compiler` rule from
`eslint-plugin-react-compiler` into the `eslint-plugin-react-hooks`
plugin. In order to do the move in a way that keeps commit history with
the moved files, but also no remove them from their origin until a
future cleanup change can be done, I did the `git mv` first, and then
recreated the files that were moved in their original places, as a
separate commit. Unfortunately GH shows the moved files as new instead
of the ones that are truly new. But in the IDE and `git blame`, commit
history is intact with the moved files.

Since this change adds new dependencies, and one of those dependencies
has a higher `engines` declaration for `node` than what the plugin
currently has, this is technically a breaking change and will have to go
out as part of a major release.

### Related Changes
- https://github.com/facebook/react/pull/32458

---------

Co-authored-by: Lauren Tan <poteto@users.noreply.github.com>
2025-03-12 21:43:06 -04:00
Miguel Jiménez EsúnandElizabeth Craig 301a18a6af react-hooks/rules-of-hooks: detect issues in class properties (#31823)
Co-authored-by: Elizabeth Craig <elcraig@microsoft.com>
2025-01-06 12:12:09 +01:00
Marin Atanasov 7c4a7c9ddf react-hooks/rules-of-hooks: Improve support for do/while loops (#31720) 2024-12-10 22:46:33 +01:00
Mark Skelton eaf2d5c670 fix[eslint-plugin-react-hooks]: Fix error when callback argument is an identifier with an as expression (#31119) 2024-11-19 10:36:30 +01:00
Marin Atanasov 9daabc0bf9 react-hooks/rules-of-hooks: Add support for do/while loops (#28714)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Currently, `react-hooks/rules-of-hooks` does not support `do/while`
loops - I've also reported this in
https://github.com/facebook/react/issues/28713.

This PR takes a stab at adding support for `do/while` by following the
same logic we already have for detecting `while` loops.

After this PR, any hooks called inside a `do/while` loop will be
considered invalid.

We're also adding some unit tests to confirm that the behavior is
working as expected.

Fixes #28713.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->

I've added unit tests that cover the case and verified that they pass by
running:

```
yarn test packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js --watch
```

I've also verified that the rest of the tests continue to pass by
running:

```
yarn test
```

and

```
yarn test --prod
```
2024-10-22 13:07:10 -07:00
Sebastian "Sebbie" Silbermann 8382581446 [ESLint] Add test for rejected useId in async Components (#31208) 2024-10-15 17:17:41 +02:00
Sebastian Silbermann 1b0132c05a Consider dispatch from useActionState stable (#29665) 2024-07-06 08:52:20 +02:00
Sebastian Silbermann 6f18664b82 eslint-plugin-react-hooks: Add support for ESLint v9 (#28773) 2024-04-23 23:29:01 +02:00
Sebastian Silbermann a540f53616 Add passing exhaustive-deps test for type parameters in TypeScript (#20432) 2024-03-14 15:41:37 +01:00
Ricky 1940cb27b2 Update /link URLs to react.dev (#28477)
Depends on https://github.com/reactjs/react.dev/pull/6670 [merged]
2024-03-03 17:34:33 -05:00
StyleShit 2efa38332a fix(eslint-plugin-react-hooks): accepting as expression as a callback (#28202)
## Summary

Closes #20750

## How did you test this change?

Added a test case
2024-02-01 21:08:21 +01:00
StyleShit a1433ca0ba fix(eslint-plugin-react-hooks): accepting as expressions as deps array (#28189)
## Summary

This PR closes #25844
The original issue talks about `as const`, but seems like it fails for
any `as X` expressions since it adds another nesting level to the AST.

EDIT: Also closes #20162

## How did you test this change?

Added unit tests
2024-02-01 20:30:17 +01:00
Ricky cc7d421629 Add lint tests that should fail (#28147)
These though fail.

Anon default export: https://github.com/facebook/react/issues/21181
Promise callbacks: https://github.com/facebook/react/issues/26186
Returning anon functions: https://github.com/facebook/react/issues/22520
2024-01-29 12:54:32 -05:00
Jan Kassens 640ccebb7d [lint] treat React.use() the same as use() (#27769)
We should probably treat `React.use()` the same as `use()` to allow it
within loops and conditionals.

Ideally this would implement a test that `React` is imported or required
from `'react'`, but we don't otherwise implement such a test.
2023-12-01 15:02:11 -05:00
Jan Kassens b8be034f07 [lint] move use lint to non-experimental (#27768)
`use` is being stabilized, so let's make sure the lint is updated for
the next release.
2023-11-30 17:39:00 -05:00
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
Andrew Clark 7118f5dd7b [ESLint] Disallow hooks in async functions (#27045)
Hooks cannot be called in async functions, on either the client or the
server. This mistake sometimes happens when using Server Components,
especially when refactoring a Server Component to a Client Component.

React logs a warning at runtime, but it's even better to catch this with
a lint rule since it will show immediate inline feedback in the editor.

I added this to the existing "Rules of Hooks" ESLint rule.
2023-07-05 11:44:28 -04:00
Sophie Alpert 767f52237c Use .slice() for all substring-ing (#26677)
- substr is Annex B
- substring silently flips its arguments if they're in the "wrong order", which is confusing
- slice is better than sliced bread (no pun intended) and also it works the same way on Arrays so there's less to remember

---

> I'd be down to just lint and enforce a single form just for the potential compression savings by using a repeated string.

_Originally posted by @sebmarkbage in https://github.com/facebook/react/pull/26663#discussion_r1170455401_
2023-04-19 14:26:01 -07:00
Jan Kassens 6b30832666 Upgrade prettier (#26081)
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.

I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
2023-01-31 08:25:05 -05:00
Sebastian Markbåge 84a0a171ea Rename experimental useEvent to useEffectEvent (#25881)
We originally had grand plans for using this Event concept for more but
now it's only meant to be used in combination with effects.

It's an Event in the FRP terms, that is triggered from an Effect.
Technically it can also be from another function that itself is
triggered from an existing side-effect but that's kind of an advanced
case.

The canonical case is an effect that triggers an event:

```js
const onHappened = useEffectEvent(() => ...);
useEffect(() => {
  onHappened();
}, []);
```
2022-12-14 15:08:29 -05:00
lauren 9336e29d91 [useEvent] Lint for presence of useEvent functions in dependency lists (#25512)
* [useEvent] Lint for presence of useEvent functions in dependency lists

With #25473, the identity of useEvent's return value is no longer stable
across renders. Previously, the ExhaustiveDeps lint rule would only
allow the omission of the useEvent function, but you could still add it
as a dependency.

This PR updates the ExhaustiveDeps rule to explicitly check for the
presence of useEvent functions in dependency lists, and emits a warning
and suggestion/autofixer for removing the dependency.
2022-10-19 12:03:46 -07:00
Andrew Clark 9cdf8a99ed [Codemod] Update copyright header to Meta (#25315)
* Facebook -> Meta in copyright

rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'

* Manual tweaks
2022-10-18 11:19:24 -04:00
Lauren Tan 3fd9bd8e74 Add RulesOfHooks support for use
Usage of the new `use` hook needs to conform to the rules of hooks, with
the one exception that it can be called conditionally.

ghstack-source-id: 7ea5beceaf
Pull Request resolved: https://github.com/facebook/react/pull/25370
2022-10-04 12:41:29 -04:00
Lauren Tan 06066c1a5a Make RulesOfHooks-test more consistent with ExhaustiveDeps-test
Small formatting changes to make the tests consistent.

ghstack-source-id: 7013a37f1f
Pull Request resolved: https://github.com/facebook/react/pull/25369
2022-09-30 15:16:22 -04:00
Lauren Tan 49ae0fad84 Fix RulesOfHooks test case indentation
Just a small formatting fix.

ghstack-source-id: c71ff02ed9
Pull Request resolved: https://github.com/facebook/react/pull/25368
2022-09-30 15:16:22 -04:00
Lauren TanandDan Abramov cb5084d1c4 [ESLint] Check useEvent references instead (#25319)
* [ESLint] Check useEvent references instead

Previously the useEvent check in RulesOfHooks would collect all
definitions of useEvent functions at the top level, record them as
violations, then clear those violations if the useEvent function was
later called or referened inside of an effect or another event.

The flaw with this approach was in the special case where useEvent
functions could be passed by reference inside of effects or events. The
violation would be cleared here (since it was called at least once)
and subsequent usages of the useEvent function would not be properly
checked.

This PR changes it so we check all identifiers that resolve to a
useEvent function, and if they are not in an effect or event must be
called or a lint error is emitted.

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>

* Add comment

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2022-09-24 01:34:17 +01:00
Lauren TanandDan Abramov c89a83695c Update RulesOfHooks with useEvent rules (#25285)
This update to the RulesOfHooks rule checks that functions created with
`useEvent` can only be invoked in a `useEffect` callback, in another
event function, or a closure.
They can't be passed down directly as a reference to child components.

This PR also updates the ExhaustiveDeps lint rule to treat useEvent's 
return value as stable, so it can be omitted from dependency lists.

Currently this all gated behind an experimental flag.

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2022-09-23 14:55:12 -07:00
Jan Kassens 2c2d9a1df0 [eslint-plugin-react-hooks] only allow capitalized component names (#25162)
- update naming rules to disallow _component
- update eslint-plugin-react-hooks version
2022-09-01 10:07:31 -04:00
Afzal Sayed 069d23bb74 [eslint-plugin-exhaustive-deps] Fix exhaustive deps check for unstable vars (#24343)
* Fix exhaustive deps for unstable vars

* Fix formatting

* Optimise iterations

* Fix linting
2022-04-11 21:43:16 +01:00
1f7a901d7b Fix false positive lint error with large number of branches (#24287)
* Switched RulesOfHooks.js to use BigInt. Added test and updated .eslintrc.js to use es2020.

* Added BigInt as readonly global in eslintrc.cjs.js and eslintrc.cjs2015.js

* Added comment to RulesOfHooks.js that gets rid of BigInt eslint error

* Got rid of changes in .eslintrc.js and yarn.lock

* Move global down

Co-authored-by: stephen cyron <stephen.cyron@fdmgroup.com>
Co-authored-by: dan <dan.abramov@gmail.com>
2022-04-08 00:22:47 +01:00
Michaël De Boey 0c0d1ddae4 feat(eslint-plugin-react-hooks): support ESLint 8.x (#22248) 2021-09-06 20:17:51 +01:00
Ricky a632f7de3b Flip tuple order of useTransition (#20976) 2021-04-20 12:21:44 -04:00
Ari Perkkiö eb58c3909a react-hooks/exhaustive-deps: Handle optional chained methods as dependency (#20204) (#20247) 2021-03-24 16:45:27 +00:00
Anthony Garritano c62986cfd8 Add additional messaging for RulesOfHooks lint error (#20692)
* Add additional messaging for RulesOfHooks lint error

* Fix tests and spacing issue

* Prettify ESLintRulesOfHooks-test
2021-02-22 19:17:13 -05:00
Christian Ruigrok e8eff119e0 Fix ESLint crash on empty react effect hook (#20385)
* Fix ESLint crash on empty react effect hook

* Add layout effect to test

* Improve wording in comment

* Improve lint warning wording

* Reword missing effect callback message
2021-01-11 15:18:45 -05:00
Sebastian Silbermann 0f70d4dd66 Consider components in jsx as missing dependencies in @typescript-eslint/parser@4.x (#19815)
* Run JS tests with TS esling parser

* Add failing test

* fix: Mark JSXIdentifier has missing dependency

* Safe isSameIdentifier
2020-09-11 13:13:43 +01:00
Sebastian Silbermann ed4fdfc737 test(eslint-plugin-react-hooks): Run with TS parsers >= 2.x (#19792)
* test(eslint-plugin-react-hooks): Run with TS parsers >= 2.x

* name test suites for each parser
2020-09-10 19:08:47 +01:00
Pascal Fong Kye 1396e4a8f5 Fixes eslint warning when node type is ChainExpression (#19680)
* Add babel parser which supports ChainExpression

* Add and fix tests for new babel eslint parser

* extract function to mark node

* refactor for compatibility with eslint v7.7.0+

* Update eslint to v7.7.0
Update hook test since eslint now supports nullish coalescing
2020-08-29 21:03:23 +01:00
Andrew Clark a8500be893 Add startTransition as a known stable method (#19720)
The `startTransition` method returned from `useTransition` is a stable
method, like `dispatch` or `setState`. You should not have to specify
it as a hook dependency.
2020-08-28 16:44:39 -07:00
CY LimandDan Abramov 702fad4b1b refactor fb.me redirect link to reactjs.org/link (#19598)
* refactor fb.me url to reactjs.org/link

* Update ESLintRuleExhaustiveDeps-test.js

* Update ReactDOMServerIntegrationUntrustedURL-test.internal.js

* Update createReactClassIntegration-test.js

* Update ReactDOMServerIntegrationUntrustedURL-test.internal.js

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2020-08-17 13:25:50 +01:00