-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Update RulesOfHooks with useEvent rules #25285
Conversation
packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
Outdated
Show resolved
Hide resolved
777fa9c
to
2639c65
Compare
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this approach quite makes sense to me. Maybe we need to discuss the rules more.
It seems like the approach you're taking is to restrict some calls to useEvent functions and passing it as JSX arguments.
I imagined the rules a bit different. I think what we need to forbid is referencing without a call. This would automatically forbid passing in JSX. But it would also forbid any other things like
const foo = onClick
return <Bar onClick={foo} />
and other variations. I think the key insight is that a bare reference like onClick
is bad, but a call like onClick()
is good.
And then, we can add back a special case that allows you to have a bare reference directly inside useEffect
as a convenience.
useEffect(() => {
let id = setInterval(onTick, 100)
return () => clearInterval(onTick)
}, [])
but this is kind of syntax sugar and not essential to the rule.
It's forbidding non-call references that's essential.
@gaearon yeah, "inverting" the logic is a great point – will fix! |
@gaearon So the lint rule now is more resilient to aliasing (and we no longer need to mess with scopes – yay!), but one small tradeoff is that you immediately get a red squiggly when you first define a function with useEvent, since it's not called anywhere yet. That's probably alright, since a similar issue happens in the ExhaustiveDeps checks. |
2ce3c01
to
4b6e620
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we add test cases for referencing event functions from useEffect
and useEvent
?
Also I'm not sure what to do with this
const onClick = useEvent(() => {});
let foo;
useEffect(() => {
foo = onClick // allowed since it's within the effect scope
})
return <Bar onClick={foo} /> // we don't know foo
@@ -406,6 +406,81 @@ const tests = { | |||
const [myState, setMyState] = useState(null); | |||
} | |||
`, | |||
` | |||
// Valid because functions created with useEvent can be called in a useEffect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: shall we just call this "event functions" like the doc (https://beta.reactjs.org/learn/separating-events-from-effects)? It's conciser and feels first classy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what exactly we want to call it (after all the recent bikeshedding) since useEvent
might be renamed, hence why I've been avoiding giving it a name. Maybe @acdlite can weigh in on what to call it in the meantime?
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
1ac4508
to
f85de77
Compare
@Huxpro @gaearon Updated to only resolve useEvent violations if the identifier is an argument into a CallExpr. But now I'm not so sure if we should still have the useEffect shorthand – we're relying on the assumption that something later invokes the useEvent function but that's not always the case. |
Why is it a problem for it to be passed in this case? I think in the normal rendering path, passing it is a problem becauase it could be used as a reactive dependency during rendering below but the reactivity is "erased". However, once you're in an Effect, you can't feed that function into a rendering path (I guess unless you put it into state? this seems pretty unlikely). Note that arbitrary functions are different because they might be called during render. So it's not OK e.g. |
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
Outdated
Show resolved
Hide resolved
f85de77
to
4622f45
Compare
This update to the lint rule checks that functions created with `useEvent` can only be invoked in a `useEffect`callback or closure. They can't be passed down directly as a reference to child components.
4622f45
to
16e669b
Compare
for (const statement of node.body.body) { | ||
if (statement.type !== 'VariableDeclaration') continue; | ||
for (const declaration of statement.declarations) { | ||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we think of any case where we'd need to go deeper or recurse? I think the only valid one I can come up with is { }
blocks that aren't conditional. Is there more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think one generalized case where we might need to go deeper is if the event function is reassigned to a variable instead of being initialized in a variable declaration:
function Component() {
let onClick;
{
onClick = useEvent(...);
}
(function weird() {
onClick = useEvent(...);
})();
// etc
}
But I don't know if this is something we want to support? I may have misunderstood the overall goal of the lint rules: do we aim to be correct in all cases, or only in the "idiomatic" case with some small exceptions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea this is not worth supporting. I think only idiomatic usage is relevant, and I guess people don't use raw blocks much either.
To keep the test simple, just imperatively only run the test if the EXPERIMENTAL flag is set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good but see last comment
9ab6ebc
to
185f3dd
Compare
packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
Outdated
Show resolved
Hide resolved
185f3dd
to
54765ee
Compare
This last test is passing but it looks like I'm getting rate limited from GitHub so the status can't update |
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 <[email protected]>
Summary: - **[9fb581c7c](facebook/react@9fb581c7c )**: Refactor: merge duplicate imports ([#25489](facebook/react#25489)) //<c0dedance>// - **[bc358362a](facebook/react@bc358362a )**: [Flight] Improve Error Messages when Invalid Object is Passed to Client/Host Components ([#25492](facebook/react#25492)) //<Sebastian Markbåge>// - **[780eacd40](facebook/react@780eacd40 )**: Flow upgrade to 0.190 ([#25483](facebook/react#25483)) //<Jan Kassens>// - **[54f0e0f73](facebook/react@54f0e0f73 )**: Scaffolding for react-dom/unstable_external-server-runtime ([#25482](facebook/react#25482)) //<Andrew Clark>// - **[0eaca3756](facebook/react@0eaca3756 )**: Add script to generate inline Fizz runtime ([#25481](facebook/react#25481)) //<Andrew Clark>// - **[69c7246d9](facebook/react@69c7246d9 )**: Initialize useMemoCache with sentinel values ([#25465](facebook/react#25465)) //<Joseph Savona>// - **[3b814327e](facebook/react@3b814327e )**: Allow Async Functions to be used in Server Components ([#25479](facebook/react#25479)) //<Sebastian Markbåge>// - **[a6bf46689](facebook/react@a6bf46689 )**: Extract Fizz instruction set to build macro ([#25457](facebook/react#25457)) //<Andrew Clark>// - **[ea5bc6bac](facebook/react@ea5bc6bac )**: [React Native FB] dynamic feature flag for ref access warning ([#25471](facebook/react#25471)) //<Jan Kassens>// - **[08d035bc8](facebook/react@08d035bc8 )**: Remove Shallow Renderer Tests ([#25475](facebook/react#25475)) //<Sebastian Markbåge>// - **[a8c16a004](facebook/react@a8c16a004 )**: Split Cache into its own Dispatcher ([#25474](facebook/react#25474)) //<Sebastian Markbåge>// - **[2cf4352e1](facebook/react@2cf4352e1 )**: Implement HostSingleton Fiber type ([#25426](facebook/react#25426)) //<Josh Story>// - **[aa9988e5e](facebook/react@aa9988e5e )**: Server render fork for react-dom ([#25436](facebook/react#25436)) //<Josh Story>// - **[513417d69](facebook/react@513417d69 )**: Return lastNonHostInstance in getInspectorDataForInstance for devtools ([#25441](facebook/react#25441)) //<Tianyu Yao>// - **[5d60a0b84](facebook/react@5d60a0b84 )**: Bugfix: LegacyHidden shouldn't defer effects ([#25442](facebook/react#25442)) //<Andrew Clark>// - **[618388bc3](facebook/react@618388bc3 )**: [Float] Support script preloads ([#25432](facebook/react#25432)) //<Josh Story>// - **[2872a26e1](facebook/react@2872a26e1 )**: track resources in different roots separately ([#25388](facebook/react#25388)) //<Josh Story>// - **[ea04a486a](facebook/react@ea04a486a )**: Flow: remove unused suppressions ([#25424](facebook/react#25424)) //<Jan Kassens>// - **[9813edef2](facebook/react@9813edef2 )**: Flow upgrade to 0.188 //<Jan Kassens>// - **[3b6826ed9](facebook/react@3b6826ed9 )**: Flow: inference_mode=constrain_writes //<Jan Kassens>// - **[aed33a49c](facebook/react@aed33a49c )**: Flow upgrade to 0.185 //<Jan Kassens>// - **[f02a5f5c7](facebook/react@f02a5f5c7 )**: Flow upgrade to 0.182 //<Jan Kassens>// - **[72593f008](facebook/react@72593f008 )**: Flow upgrade to 0.176 //<Jan Kassens>// - **[46d40f306](facebook/react@46d40f306 )**: Flow upgrade to 0.175 //<Jan Kassens>// - **[1089faf0d](facebook/react@1089faf0d )**: Flow: run codemod to remove existential type //<Jan Kassens>// - **[3fd9bd8e7](facebook/react@3fd9bd8e7 )**: Add RulesOfHooks support for `use` //<Lauren Tan>// - **[338e6a967](facebook/react@338e6a967 )**: Flow upgrade to 0.155 //<Jan Kassens>// - **[8bc95bb3c](facebook/react@8bc95bb3c )**: Flow upgrade to 0.154 //<Jan Kassens>// - **[9f8a98a39](facebook/react@9f8a98a39 )**: Flow upgrade to 0.153 //<Jan Kassens>// - **[64fe791be](facebook/react@64fe791be )**: Flow upgrade to 0.146 //<Jan Kassens>// - **[d3c6c16a0](facebook/react@d3c6c16a0 )**: Flow upgrade to 0.145 //<Jan Kassens>// - **[00a2f8150](facebook/react@00a2f8150 )**: Flow upgrade to 0.143 //<Jan Kassens>// - **[0a3072278](facebook/react@0a3072278 )**: Flow: complete types first migration ([#25389](facebook/react#25389)) //<Jan Kassens>// - **[bcc05671f](facebook/react@bcc05671f )**: Flow: types first in shared ([#25343](facebook/react#25343)) //<Jan Kassens>// - **[b1f34aa30](facebook/react@b1f34aa30 )**: Flow: types first in react-native-renderer ([#25363](facebook/react#25363)) //<Jan Kassens>// - **[9143864ae](facebook/react@9143864ae )**: Flow: well formed exports for smaller packages ([#25361](facebook/react#25361)) //<Jan Kassens>// - **[21a851e03](facebook/react@21a851e03 )**: Fix devtools typos and grammar ([#24587](facebook/react#24587)) //<Alexandru Tasica>// - **[cfafeb685](facebook/react@cfafeb685 )**: Remove extra space in Wedge.js ([#24611](facebook/react#24611)) //<Kerim Büyükakyüz>// - **[9c3de25e1](facebook/react@9c3de25e1 )**: Flow: types first in reconciler ([#25362](facebook/react#25362)) //<Jan Kassens>// - **[7b25b961d](facebook/react@7b25b961d )**: [Fizz/Float] Float for stylesheet resources ([#25243](facebook/react#25243)) //<Josh Story>// - **[4c016e7aa](facebook/react@4c016e7aa )**: Refactor: use property shorthand ([#25366](facebook/react#25366)) //<zhangrenyang>// - **[06066c1a5](facebook/react@06066c1a5 )**: Make RulesOfHooks-test more consistent with ExhaustiveDeps-test //<Lauren Tan>// - **[49ae0fad8](facebook/react@49ae0fad8 )**: Fix RulesOfHooks test case indentation //<Lauren Tan>// - **[abbbdf4ce](facebook/react@abbbdf4ce )**: Put modern StrictMode behind a feature flag ([#25365](facebook/react#25365)) //<Samuel Susla>// - **[434110390](facebook/react@434110390 )**: ReactHooks.js - delete emptyObject ([#25031](facebook/react#25031)) //<Igor Berlenko>// - **[31400ce29](facebook/react@31400ce29 )**: Refactor: merge duplicate imports ([#25364](facebook/react#25364)) //<jerry-lllman>// - **[3517bd9f7](facebook/react@3517bd9f7 )**: Refactor useEvent ([#25336](facebook/react#25336)) //<Lauren Tan>// - **[6cf06a929](facebook/react@6cf06a929 )**: Remove outdated comments. ([#24464](facebook/react#24464)) //<zhangenming>// - **[20a257c25](facebook/react@20a257c25 )**: Refactor: more word doubles removed ([#25352](facebook/react#25352)) //<Vic Graf>// - **[8cadcffd5](facebook/react@8cadcffd5 )**: Fix typo: reconcilation -> reconciliation ([#25355](facebook/react#25355)) //<zhangrenyang>// - **[ebbe599a2](facebook/react@ebbe599a2 )**: Fix EventListener fork ([#25347](facebook/react#25347)) //<Sebastian Markbåge>// - **[97d75c9c8](facebook/react@97d75c9c8 )**: Move react-dom implementation files to react-dom-bindings ([#25345](facebook/react#25345)) //<Sebastian Markbåge>// - **[3de926449](facebook/react@3de926449 )**: [Fizz] experimental_useEvent ([#25325](facebook/react#25325)) //<dan>// - **[5b59dd640](facebook/react@5b59dd640 )**: Fix duplicate words tests ([#25333](facebook/react#25333)) //<Vic Graf>// - **[cb5084d1c](facebook/react@cb5084d1c )**: [ESLint] Check useEvent references instead ([#25319](facebook/react#25319)) //<Lauren Tan>// - **[c89a83695](facebook/react@c89a83695 )**: Update RulesOfHooks with useEvent rules ([#25285](facebook/react#25285)) //<Lauren Tan>// - **[efc6a08e9](facebook/react@efc6a08e9 )**: [Flight] Implement error digests for Flight runtime and expose errorInfo in getDerivedStateFromError ([#25302](facebook/react#25302)) //<Josh Story>// - **[c1d414d75](facebook/react@c1d414d75 )**: Add ref to Offscreen component ([#25254](facebook/react#25254)) //<Samuel Susla>// - **[135e33c95](facebook/react@135e33c95 )**: Flow: typing of Scheduler ([#25317](facebook/react#25317)) //<Jan Kassens>// - **[cc8cb145f](facebook/react@cc8cb145f )**: Flow: add some missing types in react-reconciler ([#25316](facebook/react#25316)) //<Jan Kassens>// - **[112d0498c](facebook/react@112d0498c )**: [Fizz] Move digest from errorInfo to Error instance ([#25313](facebook/react#25313)) //<Josh Story>// - **[d1bb1c586](facebook/react@d1bb1c586 )**: Fix memory leak after repeated setState bailouts ([#25309](facebook/react#25309)) //<Andrew Clark>// Changelog: [General][Changed] - React Native sync for revisions 0cac4d5...9fb581c jest_e2e[run_all_tests] Reviewed By: yungsters Differential Revision: D40383219 fbshipit-source-id: dc2a44bd05df041e0c7f2e1060640b1d2c372187
Summary: - **[9fb581c7c](facebook/react@9fb581c7c )**: Refactor: merge duplicate imports ([facebook#25489](facebook/react#25489)) //<c0dedance>// - **[bc358362a](facebook/react@bc358362a )**: [Flight] Improve Error Messages when Invalid Object is Passed to Client/Host Components ([facebook#25492](facebook/react#25492)) //<Sebastian Markbåge>// - **[780eacd40](facebook/react@780eacd40 )**: Flow upgrade to 0.190 ([facebook#25483](facebook/react#25483)) //<Jan Kassens>// - **[54f0e0f73](facebook/react@54f0e0f73 )**: Scaffolding for react-dom/unstable_external-server-runtime ([facebook#25482](facebook/react#25482)) //<Andrew Clark>// - **[0eaca3756](facebook/react@0eaca3756 )**: Add script to generate inline Fizz runtime ([facebook#25481](facebook/react#25481)) //<Andrew Clark>// - **[69c7246d9](facebook/react@69c7246d9 )**: Initialize useMemoCache with sentinel values ([facebook#25465](facebook/react#25465)) //<Joseph Savona>// - **[3b814327e](facebook/react@3b814327e )**: Allow Async Functions to be used in Server Components ([facebook#25479](facebook/react#25479)) //<Sebastian Markbåge>// - **[a6bf46689](facebook/react@a6bf46689 )**: Extract Fizz instruction set to build macro ([facebook#25457](facebook/react#25457)) //<Andrew Clark>// - **[ea5bc6bac](facebook/react@ea5bc6bac )**: [React Native FB] dynamic feature flag for ref access warning ([facebook#25471](facebook/react#25471)) //<Jan Kassens>// - **[08d035bc8](facebook/react@08d035bc8 )**: Remove Shallow Renderer Tests ([facebook#25475](facebook/react#25475)) //<Sebastian Markbåge>// - **[a8c16a004](facebook/react@a8c16a004 )**: Split Cache into its own Dispatcher ([facebook#25474](facebook/react#25474)) //<Sebastian Markbåge>// - **[2cf4352e1](facebook/react@2cf4352e1 )**: Implement HostSingleton Fiber type ([facebook#25426](facebook/react#25426)) //<Josh Story>// - **[aa9988e5e](facebook/react@aa9988e5e )**: Server render fork for react-dom ([facebook#25436](facebook/react#25436)) //<Josh Story>// - **[513417d69](facebook/react@513417d69 )**: Return lastNonHostInstance in getInspectorDataForInstance for devtools ([facebook#25441](facebook/react#25441)) //<Tianyu Yao>// - **[5d60a0b84](facebook/react@5d60a0b84 )**: Bugfix: LegacyHidden shouldn't defer effects ([facebook#25442](facebook/react#25442)) //<Andrew Clark>// - **[618388bc3](facebook/react@618388bc3 )**: [Float] Support script preloads ([facebook#25432](facebook/react#25432)) //<Josh Story>// - **[2872a26e1](facebook/react@2872a26e1 )**: track resources in different roots separately ([facebook#25388](facebook/react#25388)) //<Josh Story>// - **[ea04a486a](facebook/react@ea04a486a )**: Flow: remove unused suppressions ([facebook#25424](facebook/react#25424)) //<Jan Kassens>// - **[9813edef2](facebook/react@9813edef2 )**: Flow upgrade to 0.188 //<Jan Kassens>// - **[3b6826ed9](facebook/react@3b6826ed9 )**: Flow: inference_mode=constrain_writes //<Jan Kassens>// - **[aed33a49c](facebook/react@aed33a49c )**: Flow upgrade to 0.185 //<Jan Kassens>// - **[f02a5f5c7](facebook/react@f02a5f5c7 )**: Flow upgrade to 0.182 //<Jan Kassens>// - **[72593f008](facebook/react@72593f008 )**: Flow upgrade to 0.176 //<Jan Kassens>// - **[46d40f306](facebook/react@46d40f306 )**: Flow upgrade to 0.175 //<Jan Kassens>// - **[1089faf0d](facebook/react@1089faf0d )**: Flow: run codemod to remove existential type //<Jan Kassens>// - **[3fd9bd8e7](facebook/react@3fd9bd8e7 )**: Add RulesOfHooks support for `use` //<Lauren Tan>// - **[338e6a967](facebook/react@338e6a967 )**: Flow upgrade to 0.155 //<Jan Kassens>// - **[8bc95bb3c](facebook/react@8bc95bb3c )**: Flow upgrade to 0.154 //<Jan Kassens>// - **[9f8a98a39](facebook/react@9f8a98a39 )**: Flow upgrade to 0.153 //<Jan Kassens>// - **[64fe791be](facebook/react@64fe791be )**: Flow upgrade to 0.146 //<Jan Kassens>// - **[d3c6c16a0](facebook/react@d3c6c16a0 )**: Flow upgrade to 0.145 //<Jan Kassens>// - **[00a2f8150](facebook/react@00a2f8150 )**: Flow upgrade to 0.143 //<Jan Kassens>// - **[0a3072278](facebook/react@0a3072278 )**: Flow: complete types first migration ([facebook#25389](facebook/react#25389)) //<Jan Kassens>// - **[bcc05671f](facebook/react@bcc05671f )**: Flow: types first in shared ([facebook#25343](facebook/react#25343)) //<Jan Kassens>// - **[b1f34aa30](facebook/react@b1f34aa30 )**: Flow: types first in react-native-renderer ([facebook#25363](facebook/react#25363)) //<Jan Kassens>// - **[9143864ae](facebook/react@9143864ae )**: Flow: well formed exports for smaller packages ([facebook#25361](facebook/react#25361)) //<Jan Kassens>// - **[21a851e03](facebook/react@21a851e03 )**: Fix devtools typos and grammar ([facebook#24587](facebook/react#24587)) //<Alexandru Tasica>// - **[cfafeb685](facebook/react@cfafeb685 )**: Remove extra space in Wedge.js ([facebook#24611](facebook/react#24611)) //<Kerim Büyükakyüz>// - **[9c3de25e1](facebook/react@9c3de25e1 )**: Flow: types first in reconciler ([facebook#25362](facebook/react#25362)) //<Jan Kassens>// - **[7b25b961d](facebook/react@7b25b961d )**: [Fizz/Float] Float for stylesheet resources ([facebook#25243](facebook/react#25243)) //<Josh Story>// - **[4c016e7aa](facebook/react@4c016e7aa )**: Refactor: use property shorthand ([facebook#25366](facebook/react#25366)) //<zhangrenyang>// - **[06066c1a5](facebook/react@06066c1a5 )**: Make RulesOfHooks-test more consistent with ExhaustiveDeps-test //<Lauren Tan>// - **[49ae0fad8](facebook/react@49ae0fad8 )**: Fix RulesOfHooks test case indentation //<Lauren Tan>// - **[abbbdf4ce](facebook/react@abbbdf4ce )**: Put modern StrictMode behind a feature flag ([facebook#25365](facebook/react#25365)) //<Samuel Susla>// - **[434110390](facebook/react@434110390 )**: ReactHooks.js - delete emptyObject ([facebook#25031](facebook/react#25031)) //<Igor Berlenko>// - **[31400ce29](facebook/react@31400ce29 )**: Refactor: merge duplicate imports ([facebook#25364](facebook/react#25364)) //<jerry-lllman>// - **[3517bd9f7](facebook/react@3517bd9f7 )**: Refactor useEvent ([facebook#25336](facebook/react#25336)) //<Lauren Tan>// - **[6cf06a929](facebook/react@6cf06a929 )**: Remove outdated comments. ([facebook#24464](facebook/react#24464)) //<zhangenming>// - **[20a257c25](facebook/react@20a257c25 )**: Refactor: more word doubles removed ([facebook#25352](facebook/react#25352)) //<Vic Graf>// - **[8cadcffd5](facebook/react@8cadcffd5 )**: Fix typo: reconcilation -> reconciliation ([facebook#25355](facebook/react#25355)) //<zhangrenyang>// - **[ebbe599a2](facebook/react@ebbe599a2 )**: Fix EventListener fork ([facebook#25347](facebook/react#25347)) //<Sebastian Markbåge>// - **[97d75c9c8](facebook/react@97d75c9c8 )**: Move react-dom implementation files to react-dom-bindings ([facebook#25345](facebook/react#25345)) //<Sebastian Markbåge>// - **[3de926449](facebook/react@3de926449 )**: [Fizz] experimental_useEvent ([facebook#25325](facebook/react#25325)) //<dan>// - **[5b59dd640](facebook/react@5b59dd640 )**: Fix duplicate words tests ([facebook#25333](facebook/react#25333)) //<Vic Graf>// - **[cb5084d1c](facebook/react@cb5084d1c )**: [ESLint] Check useEvent references instead ([facebook#25319](facebook/react#25319)) //<Lauren Tan>// - **[c89a83695](facebook/react@c89a83695 )**: Update RulesOfHooks with useEvent rules ([facebook#25285](facebook/react#25285)) //<Lauren Tan>// - **[efc6a08e9](facebook/react@efc6a08e9 )**: [Flight] Implement error digests for Flight runtime and expose errorInfo in getDerivedStateFromError ([facebook#25302](facebook/react#25302)) //<Josh Story>// - **[c1d414d75](facebook/react@c1d414d75 )**: Add ref to Offscreen component ([facebook#25254](facebook/react#25254)) //<Samuel Susla>// - **[135e33c95](facebook/react@135e33c95 )**: Flow: typing of Scheduler ([facebook#25317](facebook/react#25317)) //<Jan Kassens>// - **[cc8cb145f](facebook/react@cc8cb145f )**: Flow: add some missing types in react-reconciler ([facebook#25316](facebook/react#25316)) //<Jan Kassens>// - **[112d0498c](facebook/react@112d0498c )**: [Fizz] Move digest from errorInfo to Error instance ([facebook#25313](facebook/react#25313)) //<Josh Story>// - **[d1bb1c586](facebook/react@d1bb1c586 )**: Fix memory leak after repeated setState bailouts ([facebook#25309](facebook/react#25309)) //<Andrew Clark>// Changelog: [General][Changed] - React Native sync for revisions 0cac4d5...9fb581c jest_e2e[run_all_tests] Reviewed By: yungsters Differential Revision: D40383219 fbshipit-source-id: dc2a44bd05df041e0c7f2e1060640b1d2c372187
##### [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))
Summary
This update to the RulesOfHooks lint rule checks that functions created with
useEvent
must be invoked locally within the component its defined in at least once. They can't be passed down directly as a reference to child components.In the ExhaustiveDeps lint rule,
useEvent
is treated as stable, and thus does not need to be included within dependency lists.Supersedes #25121.
How did you test this change?
Added new tests.