diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 8f33b258eb..b6f2fb6337 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -972,6 +972,26 @@ const tests = { } `, }, + { + code: ` + function Example() { + const foo = useCallback(() => { + foo(); + }, []); + } + `, + }, + { + code: ` + function Example({ prop }) { + const foo = useCallback(() => { + if (prop) { + foo(); + } + }, [prop]); + } + `, + }, ], invalid: [ { @@ -4441,6 +4461,52 @@ const tests = { `This lets you handle multiple requests without bugs.`, ], }, + { + code: ` + function Example() { + const foo = useCallback(() => { + foo(); + }, [foo]); + } + `, + output: ` + function Example() { + const foo = useCallback(() => { + foo(); + }, []); + } + `, + errors: [ + "React Hook useCallback has an unnecessary dependency: 'foo'. " + + 'Either exclude it or remove the dependency array.', + ], + }, + { + code: ` + function Example({ prop }) { + const foo = useCallback(() => { + prop.hello(foo); + }, [foo]); + const bar = useCallback(() => { + foo(); + }, [foo]); + } + `, + output: ` + function Example({ prop }) { + const foo = useCallback(() => { + prop.hello(foo); + }, [prop]); + const bar = useCallback(() => { + foo(); + }, [foo]); + } + `, + errors: [ + "React Hook useCallback has a missing dependency: 'prop'. " + + 'Either include it or remove the dependency array.', + ], + }, ], }; diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index d90e980859..39f349b07b 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -401,6 +401,16 @@ export default { }); } + // Ignore references to the function itself as it's not defined yet. + const def = reference.resolved.defs[0]; + if ( + def != null && + def.node != null && + def.node.init === node.parent + ) { + continue; + } + // Add the dependency to a map so we can make sure it is referenced // again in our dependencies array. Remember whether it's static. if (!dependencies.has(dependency)) {