Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make prefer-stateless-function PureComponent aware #781

Merged
merged 2 commits into from
Aug 23, 2016

Conversation

teameh
Copy link
Contributor

@teameh teameh commented Aug 21, 2016

prefer-stateless-function should not return a warning when the user uses PureComponent to opt in for free optimisations with shouldComponentUpdate and is using props or context.

Current false positive:

class Foo extends React.PureComponent {
  render() {
    return <div>{this.props.foo}</div>;
  }
}

I first only added the same isPureComponent check as require-optimization does. But realized that components that are extending form PureComponent but don't use this.props or this.context should be written as a pure function as well. So I had to change the existing checks a bit to check that too.

Yeah I know, I could have first reacted to the discussion at #777, but I thought it would be cool to find out how all the 'rules' in eslint work by trying to fix this issue. Hope you agree about the false positive. I think this case is different from #777 because that case it not using props or context at all.

Please correct any formatting fails, first contribution here.

}

return false;
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this function should go in lib/util/Components.js

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

@lencioni
Copy link
Collaborator

This seems like a good change to me. I think it could be DRYed up a little with some of the code borrowed from other rules.

The only question I have is--should this be the behavior for everyone, or should it be an option? I'm inclined to think it can be the behavior for everyone for the sake of simplicity, but I'd like to hear opinions on that.

@teameh
Copy link
Contributor Author

teameh commented Aug 21, 2016

Thanks for the quick response.

Yeah I changed as little as possible. Just let me know if you want me to move some of it to the utils. That makes sense.

* presence of `ref` attribute in JSX
* `render` method that return anything but JSX: `undefined`, `null`, etc. (only in React <15.0.0, see [shared settings](https://github.com/yannickcr/eslint-plugin-react/blob/master/README.md#configuration) for React version configuration)

If none of these 4 elements are found, the rule will warn you to write this component as a pure function.
If none of these 5 elements are found, the rule will warn you to write this component as a pure function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just make this say "these elements" to avoid having to update the count in the future.

@ljharb
Copy link
Member

ljharb commented Aug 21, 2016

I'm -1 on this, per #777.

@teameh
Copy link
Contributor Author

teameh commented Aug 21, 2016

on #777

You should be preferring a stateless function there, since there's no state. "PureComponent" usage doesn't affect this rule by design.

But if the user chose to use PureComponent instead of Component and uses props or context, doesn't that indicate that the user want's the component to only update if the props or context changes? And that's not possible with a stateless component.

And if this is not desired then there should also be a warning when the user implemented shouldComponentUpdate or used the PureRenderMixin right? And both are not triggering a warning now.

@ljharb
Copy link
Member

ljharb commented Aug 21, 2016

If the user wants to convey their intentions to ignore this rule that prefers components without state be SFCs, they can do that with an eslint override.

While I agree that implementing shouldComponentUpdate means that the component can't be blindly made into an SFC, I think that if a React.createClass implements PureRenderMixin, but in all other respects should be an SFC - that it should be a warning.

@lencioni
Copy link
Collaborator

lencioni commented Aug 21, 2016

Yeah I was originally thinking that using PureComponent was a strong indication that the developer prefers this over an SFC, but taking a step back I don't think that's accurate. I agree that this should be handled on a case by case basis with an eslint override and not by weakening this rule.

@teameh
Copy link
Contributor Author

teameh commented Aug 21, 2016

Okay, fair enough.

But currently it's not possible to globally override this rule in .eslintrc so that it doesn't trigger a warning when PureComponent is used right?

@ljharb
Copy link
Member

ljharb commented Aug 22, 2016

@tiemevanveen that's true - making an option to prefer-stateless-function like "ignorePureComponents" might be worth doing, however?

@teameh
Copy link
Contributor Author

teameh commented Aug 22, 2016

Added the option. Also moved isPureComponent(node) to the utils in Components.js.

* Check if the node is returning JSX
*
* @param {ASTNode} ASTnode The AST node being checked
* @param {ASTNode} node The AST node being checked
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the other methods say 'node'..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This token should match the argument name, so you should update line 222 at the same time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check. And that's not possible because node is reassigned afterwards. Changed back tot original value. Thanks.

@teameh
Copy link
Contributor Author

teameh commented Aug 22, 2016

You're right, thanks.

Fixed and added to last commit.

Also removed the === true form 'no-multi-comp' where I stole the example from in the first place ;)


### `ignorePureComponent`

When `true` the rule will ignore Components extending from `React.PureComponent` that use `this.props` or `this.context`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you indicate the default value here please?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (added to commit).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to push.. done now


The following patterns is considered okay and does not cause warnings:

```js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: please make these jsx instead of js, for best syntax highlighting

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@yannickcr yannickcr merged commit 7024678 into jsx-eslint:master Aug 23, 2016
@yannickcr
Copy link
Member

Merged, thanks!

@teameh
Copy link
Contributor Author

teameh commented Aug 23, 2016

Thanks!


```js
...
"prefer-stateless-function": [<enabled>, { "ignorePureComponent": <ignorePureComponent> }]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ignorePureComponents not ignorePureComponent

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed in 9f76459

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

5 participants