diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js index 3d60a36824d2..a4853cb46149 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js @@ -74,6 +74,19 @@ const allTests = { } `, }, + { + code: normalizeIndent` + // Valid because components can be static members. + function MyComponent() { + return ; + } + + MyComponent.Ready = () => { + useHook(); + return null; + }; + `, + }, { code: normalizeIndent` // Valid because hooks can use hooks. diff --git a/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts b/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts index ca82c99e2f55..77ecce7e22f7 100644 --- a/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts +++ b/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts @@ -55,7 +55,12 @@ function isHook(node: Node): boolean { * always start with an uppercase letter. */ function isComponentName(node: Node): boolean { - return node.type === 'Identifier' && /^[A-Z]/.test(node.name); + return ( + (node.type === 'Identifier' && /^[A-Z]/.test(node.name)) || + (node.type === 'MemberExpression' && + !node.computed && + isComponentName(node.property)) + ); } function isReactFunction(node: Node, functionName: string): boolean {