jsx-eslint / eslint-plugin-react

React-specific linting rules for ESLint
MIT License
9k stars 2.77k forks source link

[jsx-handler-names] Option to enforce only for class methods #358

Open IanVS opened 8 years ago

IanVS commented 8 years ago

This is a useful rule, but it can sometimes get annoying when I want to use a prop or a method from a library directly as a handler. I think the real benefit to the rule is to force me to name my component's methods appropriately, but as it currently works, I sometimes need to do silly things like const handleSelect = props.entities.toggleItem;.

I would really like an option which prevents:

<MyComponent onChange={this.doSomething} />

// or in a stateless component:

<MyComponent onChange={doSomething} />

but still allows:

<MyComponent onChange={library.doSomething} />

<MyComponent onChange={this.props.doSomething} />

// or in a stateless component:

<MyComponent onChange={props.doSomething} />

Does that make any sense?

palnes commented 8 years ago

I second this one, plenty boilerplate if you import a library. OTOH, it might be better to abstract libraries away in this manner? But would be nice to have a choice.

lencioni commented 8 years ago

I'd be happy to review a PR that adds this as an option.

robatwilliams commented 6 years ago

Some of this, I think, could be covered reasonably straightforwardly by checking the prefix of the handler name. Only apply the rule if it begins with (this. but not this.props) or something other than props.

But I don't think that's a good approach. It's unchecked by default, can be bypassed quite easily, and would remove all enforcement when using destructured props. Anything more advanced would need to know about more than just the JSXAttribute. Any pointers on other rules that could inspire an approach?

(First time here looking at rule implementation)

deerawan commented 1 year ago

I think this option could solve my problem as well. I have a situation where I want to avoid the rule to check method from prop

This below is valid because onStop comes from property

// GOOD
interface CarProps {
  brand: string;
  onStop: () => void;
}

const Car = ({ brand, onStop }: CarProps) => {
  return (
    <h1>{brand}</h1>
    <button onClick={onStop} />Stop</button>
  )
}

However, the rule will fail if I have this component method

// BAD
interface CarProps {
  brand: string;
}

const Car = ({ brand }: CarProps) => {
  // It should be `handleStop`
  const onStop = () => { console.log('stop'); }

  return (
    <h1>{brand}</h1>
    <button onClick={onStop} />Stop</button>
  )
}
ljharb commented 1 year ago

Why not ({ brand, onStop: handleClick }): CarProps) => {?