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

Add no-mutation-props rule #1145

Closed
wants to merge 2 commits into from
Closed

Conversation

ianschmitz
Copy link

PR for #1113.

Note the change in /index.js to the recommended rules. Not sure if this rule should be part of the recommended set or not?

@ljharb This does not currently warn any time the entire props object is passed to a function. It currently has the same checks as the no-direct-mutation-state rule.

@ianschmitz
Copy link
Author

I'm not super familiar with MobX, but it may be worth thinking about how this rule may impact those users?

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

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

Thanks! Just a few comments.

This is eslint plugin react, so if MobX deviates from React, then MobX users should disable this rule - I don't think it is important in the slightest how a react linting plugin affects non-react users.

docs: {
description: 'Prevent direct mutation of this.props',
category: 'Possible Errors',
recommended: true
Copy link
Member

Choose a reason for hiding this comment

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

Changing which rules are recommended is semver-major, so that definitely shouldn't be done in this PR.

* @returns {Boolean} True if the component is valid, false if not.
*/
function isValid(component) {
return Boolean(component && !component.mutateProps);
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 use ‼x instead of Boolean(x) to coerce to booleans - and in this case, ‼component && !component.mutateProps is sufficient

function reportMutations(component) {
var mutation;
for (var i = 0, j = component.mutations.length; i < j; i++) {
mutation = component.mutations[i];
Copy link
Member

Choose a reason for hiding this comment

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

can this use component.mutations.forEach instead of a loop?

mutation = component.mutations[i];
context.report({
node: mutation,
message: 'Do not mutate props.'
Copy link
Member

Choose a reason for hiding this comment

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

it might be nice if this error message held more information - in the message, or by providing source locations.

}

item = node.left.object;
while (item.object.property) {
Copy link
Member

Choose a reason for hiding this comment

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

what if item doesn't have a .object property?


'Program:exit': function () {
var list = components.list();
for (var component in list) {
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 use Object.keys(list).forEach if it's an object, and if it's an array, list.forEach - for..in should be avoided.

@ljharb ljharb added the new rule label Apr 9, 2017
index.js Outdated
@@ -117,6 +118,7 @@ module.exports = {
'react/jsx-uses-vars': 2,
'react/no-deprecated': 2,
'react/no-direct-mutation-state': 2,
'react/no-mutation-props': 2,
Copy link
Member

Choose a reason for hiding this comment

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

(same here - adding rules to the recommended set is semver-major, so let's remove this)

@ianschmitz
Copy link
Author

Thanks for the quick review @ljharb!

I've made the changes you requested.

```jsx
var Hello = React.createClass({
render: function() {
this.props.name = this.props.name.toUpperCase();
Copy link
Member

Choose a reason for hiding this comment

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

What about things like this.props.list.push('foo'), or other array mutators? What about delete this.props.name, or Object.defineProperty(this.props, something), or Object.assign(this.props, something)?

Copy link
Contributor

Choose a reason for hiding this comment

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

^^ Further to that, you probably also want to catch this:

const {list} = this.props;
list.push('foo');

Choose a reason for hiding this comment

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

I've got a PR submitted that builds on @ianschmitz's work and catches this and many other things as well :) #1416

@@ -0,0 +1,19 @@
# Prevent mutation of this.props (no-mutation-props)

NEVER mutate `this.props`, as all React components must act like pure functions with respect to their props.
Copy link
Contributor

Choose a reason for hiding this comment

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

"NEVER" in all-caps is a bit strong, maybe change it to "Never"? :)

Copy link
Member

Choose a reason for hiding this comment

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

I would be fine with making it stronger, but there's no such thing as "super caps"

joeybaker pushed a commit to joeybaker/eslint-plugin-react that referenced this pull request Sep 7, 2017
@joeybaker joeybaker mentioned this pull request Sep 7, 2017
@joeybaker
Copy link

@ianschmitz I hope you don't mind. I used your fork as a base and added a bunch more fixes. #1416

@ljharb @Daniel15 I'd love to get that PR looked at, and if it's good, we can port nearly all of it to the no-direct-mutation-state rule to dramatically improve it.

@ianschmitz
Copy link
Author

Not at all @joeybaker. Sorry, I've fell out of touch with this PR 😢

Thanks for helping out everyone!

@ianschmitz
Copy link
Author

Closing in favor of the updated PR over at #1416. Thanks @joeybaker !

@ianschmitz ianschmitz closed this Sep 7, 2017
@ljharb
Copy link
Member

ljharb commented Sep 7, 2017

In the future it'd be preferable to ask maintainers to add your commits to the original PR; replacement PRs are clutter.

@joeybaker
Copy link

@ljharb Sounds good. I'm happy for you to do that and close the new PR :)

@ljharb
Copy link
Member

ljharb commented Sep 7, 2017

Nah at this point it's open, we'll continue with that :-)

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

Successfully merging this pull request may close these issues.

4 participants