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

react/jsx-handler-names creates unnecessary friction for destructured props

Open y-hsgw opened this issue 8 months ago • 0 comments

This rule is well thought out and has helped enforce consistency in many codebases. However, there was one area that concerned me, so I created this issue.

Summary

When defining components, developers can choose to access props either via props.onClick or destructure them like { onClick }. However, react/jsx-handler-names treats these two approaches differently:

// ✅ No lint error
const Component = (props) => <Button onClick={props.onClick} />;

// ❌ Lint error
const Component = ({ onClick }) => <Button onClick={onClick} />;

This rule appears to be intentional (as acknowledged here), but in practice I believe it creates several issues that reduce clarity and developer experience:

Problem

The core issue seems to be that the rule behaves differently based purely on whether props are destructured or not — even though both cases appear to refer to the same underlying value. This difference in behavior may feel inconsistent and confusing, as destructuring is simply a syntactic convenience that does not alter the meaning or usage of the value.

// ✅ props used directly — no lint error
export const Component = (props) => {
  const handleClick = () => {
    props.onClick();
    console.log("clicked");
  };

  return (
    <>
      <Button onClick={props.onClick} />
      <Button onClick={handleClick} />
    </>
  );
};

// ❌ destructured prop — lint error on `onClick`
export const Component = ({ onClick }) => {
  const handleClick = () => {
    onClick();
    console.log("clicked");
  };

  return (
    <>
      <Button onClick={onClick} />      // ⚠️ Lint error here
      <Button onClick={handleClick} />
    </>
  );

This is just one example, but to avoid this lint error, developers must think about how to rename the destructured prop or avoid naming collisions — something that isn't necessary when using props.onClick. This adds extra mental overhead compared to the direct props usage.

Suggestion

I believe it would be helpful for the rule to handle both forms consistently.

Possible resolutions might include:

  • Allowing destructured props to avoid triggering the rule, just like direct prop access
  • Introducing an option like checkDestructuredProps: false to let teams configure this behavior
  • Or, alternatively, clarifying why destructured props should be treated differently, if that's intentional — in which case, understanding that reasoning could help inform best practices and improve adoption

Thanks for your consideration!

similar issue: https://github.com/jsx-eslint/eslint-plugin-react/issues/358

y-hsgw avatar Apr 05 '25 05:04 y-hsgw