@samitouri / QOS-React-1 / commits / 4448b18760

[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;