-
Notifications
You must be signed in to change notification settings - Fork 191
isHookCall doesn't detect namespace hook calls (React.useState, React.useEffect, etc.) #117
Description
Bug
isHookCall only checks node.callee?.type === "Identifier" — it never handles MemberExpression (React.useEffect).
Current implementation
const isHookCall = (node, hookName) =>
node.type === "CallExpression" &&
node.callee?.type === "Identifier" &&
(typeof hookName === "string"
? node.callee.name === hookName
: hookName.has(node.callee.name));This only matches direct calls like useEffect(...) where the callee is an Identifier. It does not match React.useEffect(...) where the callee is a MemberExpression ({ object: { name: "React" }, property: { name: "useEffect" } }).
Impact
Every rule that uses isHookCall silently misses namespace-style hook calls. This affects:
no-derived-state-effectno-fetch-in-effectno-cascading-set-stateno-effect-event-handler- and others
Additionally, isSetterIdentifier checks inside rule bodies only match Identifier callee types, missing React.useState setter patterns (e.g. in countSetStateCalls, noDerivedStateEffect, rerenderFunctionalSetstate, renderingHydrationNoFlicker).
Steps to reproduce
// DETECTED (named import)
import { useState, useEffect } from 'react';
const [label, setLabel] = useState('');
useEffect(() => { setLabel(`${value}-x`); }, [value]);
// NOT DETECTED (namespace import — very common pattern)
import * as React from 'react';
const [label, setLabel] = React.useState('');
React.useEffect(() => { setLabel(`${value}-x`); }, [value]);Run npx react-doctor . --verbose on each — only the named import version flags no-derived-state-effect.