Skip to content

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

Open
@y-hsgw

Description

@y-hsgw

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: #358

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions