diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 348221cd2bdae..79713c57cdec8 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -178,6 +178,16 @@ const tests = { } `, }, + { + // Valid because they have meaning without deps. + code: ` + function MyComponent(props) { + useEffect(() => {}); + useLayoutEffect(() => {}); + useImperativeHandle(props.innerRef, () => {}); + } + `, + }, { code: ` function MyComponent(props) { @@ -924,6 +934,26 @@ const tests = { 'Either include it or remove the dependency array.', ], }, + { + // Invalid because they don't have a meaning without deps. + code: ` + function MyComponent(props) { + const value = useMemo(() => { return 2*2; }); + const fn = useCallback(() => { alert('foo'); }); + } + `, + // We don't know what you meant. + output: ` + function MyComponent(props) { + const value = useMemo(() => { return 2*2; }); + const fn = useCallback(() => { alert('foo'); }); + } + `, + errors: [ + "React Hook useMemo doesn't serve any purpose without a dependency array as a second argument.", + "React Hook useCallback doesn't serve any purpose without a dependency array as a second argument.", + ], + }, { // Regression test code: ` diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index 58a5d2a25dff7..51efab5f5dee7 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -87,6 +87,18 @@ export default { const depsIndex = callbackIndex + 1; const declaredDependenciesNode = node.parent.arguments[depsIndex]; if (!declaredDependenciesNode) { + // These are only used for optimization. + if ( + reactiveHookName === 'useMemo' || + reactiveHookName === 'useCallback' + ) { + context.report({ + node: node, + message: + `React Hook ${reactiveHookName} doesn't serve any purpose ` + + `without a dependency array as a second argument.`, + }); + } return; }