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

Warns when mutated props are passed. #5346

Merged
merged 1 commit into from
Dec 17, 2015

Conversation

ManasJayanth
Copy link
Contributor

Attempts for fix #5335

@@ -147,6 +147,7 @@ var ReactCompositeComponentMixin = {
// Initialize the public class
var inst;
var renderedElement;
var propsMuted = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

did you mean mutated?

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@ManasJayanth
Copy link
Contributor Author

@jimfb Good enough?

if (propsMutated) {
warning(
propsMutated,
'Mutated props not allowed in %s(...)',
Copy link
Contributor

Choose a reason for hiding this comment

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

If someone is debugging, just saying "Mutated props not allowed in..." doesn't really describe what's wrong. Someone who is writing a moderately complex component might not see what the issue is.

I would say something like "Constructor (of %s) may not invoke super(...) with props that differ from the props that were initially passed in from the component's owner."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

@jimfb
Copy link
Contributor

jimfb commented Nov 3, 2015

Also, are you sure this works? I thought we set inst.props to always be publicProps (the diff that proposed changing this is what spawned the whole discussion). Anyway, we should add a unit test to assert the warning fires as expected.

@ManasJayanth
Copy link
Contributor Author

@jimfb Warning does show for the component. However, it is also triggered for another component TopLevelWrapper everywhere. This leads to all warning related tests to fail.

What is TopLevelWrapper for anyways?

@jimfb
Copy link
Contributor

jimfb commented Nov 4, 2015

@prometheansacrifice TopLevelWrapper is created at the top/root of each render tree. It is a temporary (?) hack so that we can store all top-level pending updates on composites instead of having to worry about different types of components.

I'm a little surprised that TopLevelWrapper warns, since I wouldn't expect it to be doing anything fancy with props. The entire definition (in ReactMount.js) is literally only a few lines:

var TopLevelWrapper = function() {};
TopLevelWrapper.prototype.isReactComponent = {};
if (__DEV__) {
  TopLevelWrapper.displayName = 'TopLevelWrapper';
}
TopLevelWrapper.prototype.render = function() {
  // this.props is actually a ReactElement
  return this.props;
};  

Anyway, we should fix so it doesn't warn for TopLevelWrapper.

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@sophiebits
Copy link
Collaborator

Let's also not warn if you pass up undefined (e.g., super();). In examples we've indicated that you only need to pass up props if you want to access this.props in the constructor (same with context as a second arg).

return <span />;
};

function Bar (props) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you need Foo at all? Why can't Bar extend React.Component directly?

Also, can you use ES6 class syntax here? It's simpler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. Foo (or Bar) can directly inherit. Making the change in the next commit.

Is ES6 necessary here? I find most of the React Component definition is ES5 syntax. Simpler as it maybe, mixing up the syntax looks bad on the file as a whole.

Copy link
Contributor

Choose a reason for hiding this comment

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

We're slowly transitioning to ES6. You'll notice that ES6 syntaxes have been appearing in the docs too; most of the new stuff uses ES6.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright then.

@ManasJayanth ManasJayanth changed the title Warns when muted props are passed. Warns when mutated props are passed. Nov 5, 2015
@ManasJayanth
Copy link
Contributor Author

@jimfb Is the behaviour correct in the first place? Is it okay for TopLevelWrapper to pass mutated props to super() ? Or should I ignore it in the test with a Component.displayName !== 'TopLevelWrapper'

@sophiebits
Copy link
Collaborator

TopLevelWrapper doesn't call super at all (which is allowed). Look at its definition in ReactMount. You should not ignore it with a check for its displayName.

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@ManasJayanth
Copy link
Contributor Author

@spicyj Added the fix. Can you please review once again?

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@@ -195,6 +196,18 @@ var ReactCompositeComponentMixin = {
Component.displayName || Component.name || 'Component'
);
}

var propsMutated = !shallowEqual(inst.props || {}, publicProps);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This must use ===, not shallowEqual.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By ===, you mean deep comparison of objects? I remember @jimfb asking me to avoid as it is expensive.

Copy link
Collaborator

Choose a reason for hiding this comment

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

=== just checks if they are the same reference; it is less expensive than shallowEqual.

@facebook-github-bot
Copy link

@prometheansacrifice updated the pull request.

@ManasJayanth
Copy link
Contributor Author

@jimfb @spicyj Does this PR need more work?

@sophiebits
Copy link
Collaborator

@prometheansacrifice Sorry for the delay. This seems good – thank you.

sophiebits added a commit that referenced this pull request Dec 17, 2015
@sophiebits sophiebits merged commit 963b3ca into facebook:master Dec 17, 2015
@ManasJayanth
Copy link
Contributor Author

@spicyj Thank you too :)

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

Successfully merging this pull request may close these issues.

Warn if people pass in "mutated" props
5 participants