Commit Graph

45 Commits

Author SHA1 Message Date
João Eirinha
2381ecc290
[ESLint] Disallow passing effect event down when inlined as a prop (#34820)
## Summary

Fixes https://github.com/facebook/react/issues/34793.

We are allowing passing down effect events when they are inlined as a
prop.

```
<Child onClick={useEffectEvent(...)} />
```

This seems like a case that someone not familiar with `useEffectEvent`'s
purpose could fall for so this PR introduces logic to disallow its
usage.

An alternative implementation would be to modify the name and function
of `recordAllUseEffectEventFunctions` to record all `useEffectEvent`
instances either assigned to a variable or not, but this seems clearer.
Or we could also specifically disallow its usage inside JSX. Feel free
to suggest any improvements.

## How did you test this change?

- Added a new test in
`packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js`.
All tests pass.
2025-10-16 14:18:01 -04:00
Jack Pope
67e24bc527
Improve lint error messages for useEffectEvent (#34669)
Called Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component.

Called After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.

Referenced Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component. They cannot be assigned to
variables or passed down.

Referenced After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.
It cannot be assigned to a variable or passed down.
2025-10-01 15:17:08 -04:00
Jack Pope
57b16e3788
[lint] Remove experimental gating useEffectEvent rules (#34660)
Stacked on https://github.com/facebook/react/pull/34637

`useEffectEvent` is now in canary so we need to remove this
`__EXPERIMENTAL__` gating on the rules and tests
2025-09-30 16:55:56 -04:00
Jordan Brown
92cfdc3a4e
[lint] Enable custom hooks configuration for useEffectEvent calling rules (#34497)
We need to be able to specify additional effect hooks for the
RulesOfHooks lint rule
in order to allow useEffectEvent to be called by custom effects.
ExhaustiveDeps
does this with a regex suppplied to the rule, but that regex is not
accessible from
other rules.

This diff introduces a `react-hooks` entry you can put in the eslint
settings that
allows you to specify custom effect hooks and share them across all
rules.

This works like:
```
{
  settings: {
    'react-hooks': {
      additionalEffectHooks: string,
    },
  },
}
```

The next diff allows useEffect to read from the same configuration.


----

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34497).
* #34637
* __->__ #34497
2025-09-30 16:44:22 -04:00
Jordan Brown
e02c173fa5
[lint] Allow useEffectEvent in useLayoutEffect and useInsertionEffect (#34492)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34492).
* #34497
* __->__ #34492
2025-09-23 16:56:09 -04:00
Joseph Savona
7d29ecbeb2
[compiler] Aggregate error reporting, separate eslint rules (#34176)
NOTE: this is a merged version of @mofeiZ's original PR along with my
edits per offline discussion. The description is updated to reflect the
latest approach.

The key problem we're trying to solve with this PR is to allow
developers more control over the compiler's various validations. The
idea is to have a number of rules targeting a specific category of
issues, such as enforcing immutability of props/state/etc or disallowing
access to refs during render. We don't want to have to run the compiler
again for every single rule, though, so @mofeiZ added an LRU cache that
caches the full compilation output of N most recent files. The first
rule to run on a given file will cause it to get cached, and then
subsequent rules can pull from the cache, with each rule filtering down
to its specific category of errors.

For the categories, I went through and assigned a category roughly 1:1
to existing validations, and then used my judgement on some places that
felt distinct enough to warrant a separate error. Every error in the
compiler now has to supply both a severity (for legacy reasons) and a
category (for ESLint). Each category corresponds 1:1 to a ESLint rule
definition, so that the set of rules is automatically populated based on
the defined categories.

Categories include a flag for whether they should be in the recommended
set or not.

Note that as with the original version of this PR, only
eslint-plugin-react-compiler is changed. We still have to update the
main lint rule.

## Test Plan

* Created a sample project using ESLint v9 and verified that the plugin
can be configured correctly and detects errors
* Edited `fixtures/eslint-v9` and introduced errors, verified that the w
latest config changes in that fixture it correctly detects the errors
* In the sample project, confirmed that the LRU caching is correctly
caching compiler output, ie compiling files just once.

Co-authored-by: Mofei Zhang <feifei0@meta.com>
2025-08-21 14:53:34 -07:00
Benjamin
87a45ae37f
[eslint-plugin-react-hooks][RulesOfHooks] handle React.useEffect in addition to useEffect (#34076)
## Summary

This is a fix for https://github.com/facebook/react/issues/34074

## How did you test this change?

I added tests in the eslint package, and ran `yarn jest`. After adding
the new tests, I have this:

On main | On this branch
-|-
<img width="356" height="88" alt="image"
src="https://github.com/user-attachments/assets/4ae099a1-0156-4032-b2ca-635ebadcaa3f"
/> | <img width="435" height="120" alt="image"
src="https://github.com/user-attachments/assets/b06c04b8-6cec-43de-befa-a8b4dd20500e"
/>

## Changes

- Add tests to check that we are checking both `CallExpression`
(`useEffect(`), and `MemberExpression` (`React.useEffect(`). To do that,
I copied the `getNodeWithoutReactNamespace(` fn from `ExhaustiveDeps.ts`
to `RulesOfHooks.ts`
2025-08-18 09:12:49 -04:00
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
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
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
Miguel Jiménez Esún
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
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
6f18664b82
eslint-plugin-react-hooks: Add support for ESLint v9 (#28773) 2024-04-23 23:29:01 +02: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
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
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
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 Tan
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 Tan
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
Stephen Cyron
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
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
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
Rohith Srivathsav
ddcc69c83b
Added clear message for functional component starting with lowercase (#18881) 2020-05-10 01:52:11 +01:00
Chang Yan
4b02b66111
[ESLint] Extend isHook to recognize those under PascalCase's namespace (#18722)
* Extend Namespace to PascalCase

* Add valid case for jest.useFakeTimer

* format

* format :(

* fix nits
2020-04-24 02:50:52 +01:00
Ian Obermiller
d3368beeec
[eslint-plugin-react-hooks] Disallow hooks in class components (#18341)
Per discussion at Facebook, we think hooks have reached a tipping point where it is more valuable to lint against potential hooks in classes than to worry about false positives.

Test plan:
```
# run from repo root
yarn test --watch RuleOfHooks
```
2020-03-18 19:55:13 +00:00
Moji Izadmehr
bf13d3e3c6
[eslint-plugin-react-hooks] Fix cyclic caching for loops containing a… (#16853)
* [eslint-plugin-react-hooks] Fix cyclic caching for loops containing a condition

* [eslint-plugin-react-hooks] prettier write

* [eslint-plugin-react-hooks] Fix set for tests

* Update packages/eslint-plugin-react-hooks/src/RulesOfHooks.js

Co-Authored-By: Luke Kang <kidkkr@icloud.com>

Co-authored-by: Luke Kang <kidkkr@icloud.com>
2020-02-25 11:38:23 +00:00
David Garner
a807c307c4 [eslint] Check forwardRef callbacks (#17255)
* [eslint] Check forwardRef callbacks (#17220)

* [eslint] Make tests more realistic (#17220)

* [eslint] Check anonymous callback of React.memo for rules-of-hooks (#17220)

* [eslint] Add tests for callbacks not known to be components (#17220)

* [eslint] Correct comments and add another test (#17220)
2019-11-17 13:39:08 +00:00
Rane Wallin
5943b1da6c Fixing grammatical errors in error message (#16973)
* Fixing grammatical errors in error message

* Fixing grammar error in test file
2019-10-03 18:14:48 +05:30
Dan Abramov
c433fbb593
Revert "Revert "[ESLint] Forbid top-level use*() calls (#16455)"" (#16525)
* Revert "Revert "[ESLint] Forbid top-level use*() calls (#16455)" (#16522)"

This reverts commit 507f0fb372.

* Update RulesOfHooks.js
2019-08-21 15:43:31 +01:00
Sunil Pai
507f0fb372
Revert "[ESLint] Forbid top-level use*() calls (#16455)" (#16522)
This reverts commit 96eb703bbf.
2019-08-21 10:20:34 +01:00
Dan Abramov
96eb703bbf
[ESLint] Forbid top-level use*() calls (#16455)
* Add a way to skip/only tests to RulesOfHooks test

* [ESLint] Forbid top-level use*() calls

* Add a regression test for logical expressions

This is not a change. Just adding more coverage.
2019-08-19 19:54:06 +01:00
Simen Bekkhus
e308a037be chore: make tests compatible with Jest 24 (#15779)
* chore: make tests compatible with Jest 24

* remove fake rafs

* rollback jsdom for localstorage compat

* Apply suggestions from code review

Co-Authored-By: Sunil Pai <threepointone@oculus.com>

* chore: cleanup lockfile
2019-08-14 12:32:26 +01:00
Thomas Broyer
7439b48cf4 Add explicit support for ESLint 6.0.0 (#15974)
Preemptively update tests wrt 'parser' requiring an absolute
path rather than a package name, even though the project is
still using ESLint 4.

Fixes #15971
2019-06-24 22:30:12 +01:00
Yurick
e19c9e1064 Fix issue with multiple code branches in hooks linter (#14661)
* Fix issue with multiple code branches

* Add solution by @calebmer

* Add performance test

* Undo unrelated change
2019-01-25 17:06:33 +00:00
Sophie Alpert
3db8b80e15
Don't lint against Hooks after conditional throw (#14040)
Seems like this should be OK. Fixes #14038.

Now when tracking paths, we completely ignore segments that end in a throw.
2018-10-30 17:13:24 -07:00
Caleb Meredith
ddbfe2ed50 Add ESLint rule for React Hooks 2018-10-29 11:26:54 -07:00