From 4f843be5f3ea5faeda6457d083f7b7e2a17b6562 Mon Sep 17 00:00:00 2001 From: Ari Perkkio Date: Wed, 2 Dec 2020 07:07:32 +0200 Subject: [PATCH] react-hooks/exhaustive-deps: Handle optional chained methods as dependency (#20204) --- .../ESLintRuleExhaustiveDeps-test.js | 30 +++++++++++++++++++ .../src/ExhaustiveDeps.js | 5 ++++ 2 files changed, 35 insertions(+) diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 0c782dc25ae02..f1acb08f5b604 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -3593,6 +3593,36 @@ const tests = { }, ], }, + { + code: normalizeIndent` + function MyComponent(props) { + useEffect(() => {}, [props?.attribute.method()]); + } + `, + errors: [ + { + message: + 'React Hook useEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + suggestions: undefined, + }, + ], + }, + { + code: normalizeIndent` + function MyComponent(props) { + useEffect(() => {}, [props.method()]); + } + `, + errors: [ + { + message: + 'React Hook useEffect has a complex expression in the dependency array. ' + + 'Extract it to a separate variable so it can be statically checked.', + suggestions: undefined, + }, + ], + }, { code: normalizeIndent` function MyComponent() { diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index 7c970f7c8f6ac..de221c54673ba 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -1643,6 +1643,11 @@ function analyzePropertyChain(node, optionalChains) { return result; } else if (node.type === 'ChainExpression' && !node.computed) { const expression = node.expression; + + if (expression.type === 'CallExpression') { + throw new Error(`Unsupported node type: ${expression.type}`); + } + const object = analyzePropertyChain(expression.object, optionalChains); const property = analyzePropertyChain(expression.property, null); const result = `${object}.${property}`;