eslint-plugin-react icon indicating copy to clipboard operation
eslint-plugin-react copied to clipboard

[Bug]: jsx-handler-names crashes on compound components

Open djankies opened this issue 2 months ago • 2 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues and my issue is unique
  • [x] My issue appears in the command-line and not only in the text editor

Description Overview

react/jsx-handler-names rule crashes with TypeError: Cannot read properties of undefined (reading 'split') when encountering compound components (e.g., <Component.SubComponent />).

Environment

  • eslint-plugin-react: 7.37.5
  • ESLint: 9.36.0
  • Parser: @typescript-eslint/parser

Stack Trace

TypeError: Cannot read properties of undefined (reading 'split')
    at Minimatch.match (node_modules/minimatch/minimatch.js:743:9)
    at minimatch (node_modules/minimatch/minimatch.js:125:42)
    at node_modules/eslint-plugin-react/lib/rules/jsx-handler-names.js:146:99

Root Cause

The rule incorrectly assumes node.parent.name.name exists for all components:

// Line 144 in jsx-handler-names.js
const componentName = node.parent.name.name;  // Returns undefined for compound components

const isComponentNameIgnored = ignoreComponentNames.some((pattern) => minimatch(
  componentName,  // undefined passed to minimatch
  pattern
));

AST Structure Difference

Component Type JSX node.parent.name
Simple <Button /> { type: 'JSXIdentifier', name: 'Button' }
Compound <Select.Option /> { type: 'JSXMemberExpression', object: {...}, property: {...} }

For JSXMemberExpression, there's no .name property at the root level, causing undefined to be passed to minimatch().

Minimal Reproduction

// test.jsx
const Component = () => {
  const handleChange = () => {};
  return <Select.Option onChange={handleChange} />;  // Crashes here
};
// eslint.config.mjs
export default [{
  plugins: { react: reactPlugin },
  rules: {
    'react/jsx-handler-names': ['warn', {
      eventHandlerPrefix: 'handle',
      eventHandlerPropPrefix: 'on'
    }]
  }
}];

Run: npx eslint test.jsx → TypeError

Workaround

Disable the rule for files with compound components:

export default [
  { rules: { 'react/jsx-handler-names': ['warn', {...}] } },
  {
    files: ['**/files-with-compound-components.tsx'],
    rules: { 'react/jsx-handler-names': 'off' }
  }
];

Expected Behavior

  1. Successfully parse compound components without crashing
  2. Apply handler naming conventions to compound components (e.g., warn if <Select.Option onClick={doSomething} /> doesn't follow the configured naming pattern)
  3. Support ignoreComponentNames patterns for compound components (e.g., 'Select.*' or '*.Option')

eslint-plugin-react version

v7.37.5

eslint version

v9.36.0

node version

v23.5.0

djankies avatar Sep 22 '25 01:09 djankies