[eslint-plugin-react-hooks] fix exhaustive deps lint rule with component syntax (#33182)
Jan Kassens committed
May 15, 2025 at 12:51 UTC
4448b18760d867f9e009e810571e7a3b8930bb19
2 files changed
+65
-2
packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
+58
-1
@@ -7746,6 +7746,34 @@ const testsFlow = {
7746
},
7747
],
7748
invalid: [
7749
+ {
7750
+ code: normalizeIndent`
7751
+ hook useExample(a) {
7752
+ useEffect(() => {
7753
+ console.log(a);
7754
+ }, []);
7755
+ }
7756
+ `,
7757
+ errors: [
7758
+ {
7759
+ message:
7760
+ "React Hook useEffect has a missing dependency: 'a'. " +
7761
+ 'Either include it or remove the dependency array.',
7762
+ suggestions: [
7763
+ {
7764
+ desc: 'Update the dependencies array to be: [a]',
7765
+ output: normalizeIndent`
7766
+ hook useExample(a) {
7767
+ useEffect(() => {
7768
+ console.log(a);
7769
+ }, [a]);
7770
+ }
7771
+ `,
7772
+ },
7773
+ ],
7774
+ },
7775
+ ],
7776
+ },
7777
{
7778
code: normalizeIndent`
7779
function Foo() {
@@ -8311,7 +8339,9 @@ describe('rules-of-hooks/exhaustive-deps', () => {
8339
},
8340
};
8341
8314
- const testsBabelEslint = {
8342
+ const testsBabelEslint = tests;
8343
+
8344
+ const testsHermesParser = {
8345
valid: [...testsFlow.valid, ...tests.valid],
8346
invalid: [...testsFlow.invalid, ...tests.invalid],
8347
};
@@ -8336,6 +8366,33 @@ describe('rules-of-hooks/exhaustive-deps', () => {
8366
testsBabelEslint
8367
);
8368
8369
+ new ESLintTesterV7({
8370
+ parser: require.resolve('hermes-eslint'),
8371
+ parserOptions: {
8372
+ sourceType: 'module',
8373
+ enableExperimentalComponentSyntax: true,
8374
+ },
8375
+ }).run(
8376
+ 'eslint: v7, parser: hermes-eslint',
8377
+ ReactHooksESLintRule,
8378
+ testsHermesParser
8379
+ );
8380
+
8381
+ new ESLintTesterV9({
8382
+ languageOptions: {
8383
+ ...languageOptionsV9,
8384
+ parser: require('hermes-eslint'),
8385
+ parserOptions: {
8386
+ sourceType: 'module',
8387
+ enableExperimentalComponentSyntax: true,
8388
+ },
8389
+ },
8390
+ }).run(
8391
+ 'eslint: v9, parser: hermes-eslint',
8392
+ ReactHooksESLintRule,
8393
+ testsHermesParser
8394
+ );
8395
+
8396
const testsTypescriptEslintParser = {
8397
valid: [...testsTypescript.valid, ...tests.valid],
8398
invalid: [...testsTypescript.invalid, ...tests.invalid],
packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts
+7
-1
@@ -203,7 +203,13 @@ const rule = {
203
let currentScope = scope.upper;
204
while (currentScope) {
205
pureScopes.add(currentScope);
206
- if (currentScope.type === 'function') {
206
+ if (
207
+ currentScope.type === 'function' ||
208
+ // @ts-expect-error incorrect TS types
209
+ currentScope.type === 'hook' ||
210
+ // @ts-expect-error incorrect TS types
211
+ currentScope.type === 'component'
212
+ ) {
213
break;
214
}
215
currentScope = currentScope.upper;