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 React.PureComponent #7195

Merged
merged 1 commit into from
Jul 6, 2016
Merged

Add React.PureComponent #7195

merged 1 commit into from
Jul 6, 2016

Conversation

sophiebits
Copy link
Collaborator

This provides an easy way to indicate that components should only rerender when given new props, like PureRenderMixin. If you rely on mutation in your React components, you can continue to use React.Component.

Inheriting from React.PureComponent indicates to React that your component doesn't need to rerender when the props are unchanged. We'll compare the old and new props before each render and short-circuit if they're unchanged. It's like an automatic shouldComponentUpdate.

);
}
}
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: could be else if for less nesting?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It could be but I prefer parallel structure in my if/else-if cases so I left it like this.

Copy link
Contributor

Choose a reason for hiding this comment

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

It could be but I prefer parallel structure in my if/else-if cases so I left it like this.

IMO, always good to use least syntax~

@syranide
Copy link
Contributor

syranide commented Jul 6, 2016

When documenting this I'd say it's important to note that callback handlers that are bound in render will always fail shallowEqual, many people are unaware of this and there has previously been discussions about ignoring functions in the comparison (I know this was recommended at some point).

@jimfb
Copy link
Contributor

jimfb commented Jul 6, 2016

In addition to event handlers bound in render, it is probably also worth mentioning that any component which takes jsx children will also always fail shallowEqual, since the children elements will be re-created for every render. I think most people don't realize this.

ReactComponent.call(this, props, context, updater);
}

Object.assign(ReactPureComponent.prototype, ReactComponent.prototype);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we extend ReactComponent? What about people doing instanceof React.Component even though they shouldn't?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

All right.

This provides an easy way to indicate that components should only rerender when given new props, like PureRenderMixin. If you rely on mutation in your React components, you can continue to use `React.Component`.

Inheriting from `React.PureComponent` indicates to React that your component doesn't need to rerender when the props are unchanged. We'll compare the old and new props before each render and short-circuit if they're unchanged. It's like an automatic shouldComponentUpdate.
@sophiebits sophiebits merged commit c8fbdac into facebook:master Jul 6, 2016
@STRML
Copy link
Contributor

STRML commented Jul 7, 2016

@jimfb This is mitigated somewhat in production by the babel constant elements transform, no?

@zpao zpao added this to the 15-next milestone Jul 7, 2016
usmanajmal pushed a commit to usmanajmal/react that referenced this pull request Jul 11, 2016
This provides an easy way to indicate that components should only rerender when given new props, like PureRenderMixin. If you rely on mutation in your React components, you can continue to use `React.Component`.

Inheriting from `React.PureComponent` indicates to React that your component doesn't need to rerender when the props are unchanged. We'll compare the old and new props before each render and short-circuit if they're unchanged. It's like an automatic shouldComponentUpdate.
@zpao zpao modified the milestones: 15-next, 15.3.0 Jul 13, 2016
zpao pushed a commit that referenced this pull request Jul 13, 2016
This provides an easy way to indicate that components should only rerender when given new props, like PureRenderMixin. If you rely on mutation in your React components, you can continue to use `React.Component`.

Inheriting from `React.PureComponent` indicates to React that your component doesn't need to rerender when the props are unchanged. We'll compare the old and new props before each render and short-circuit if they're unchanged. It's like an automatic shouldComponentUpdate.
(cherry picked from commit c8fbdac)
@vlucas
Copy link

vlucas commented Jul 14, 2016

Is there also going to be a React.createClass({ ... }) way to do this?

@gaearon
Copy link
Collaborator

gaearon commented Jul 14, 2016

@vlucas

For React.createClass(), you can either use PureRenderMixin or shallowCompare (both are available as addons).

@developit
Copy link
Contributor

@gaearon / @spicyj - are you guys able to confirm this will land in 15.x with the shallowEqual() approach taken in this PR?

@sophiebits
Copy link
Collaborator Author

That's the plan.

@developit
Copy link
Contributor

Great, thanks.

@slmgc
Copy link

slmgc commented Jul 15, 2016

@spicyj don't you think ReactPureComponent and isPureReactComponent look a little bit inconsistent? Could isReactPureComponent be a better name?

@sebmarkbage
Copy link
Collaborator

Actually, that's a good point. We should make it a worse name so that nobody relies on this implementation detail. :)

@brycehanscomb
Copy link

Why was the decision to implement this class favoured over making React better equipped to deal with functional stateless components?

@Jessidhia
Copy link
Contributor

@brycehanscomb I believe the intention is to add this as a non-breaking opt-in change, and then in React 16 change the internal SFC wrapper class to derive from React.PureComponent. I am just guessing, though.

@gaearon
Copy link
Collaborator

gaearon commented Jul 30, 2016

It's a stepping stone. We'll keep thinking about optimizing functional stateless components.

However just making every one of them work like PureComponent can slow down your app. Please don't think shallow equality checks are extremely cheap. They can help your app when placed strategically but just making every single component pure can actually make your app slower. Tradeoffs.

For now we added a base class because we wanted an official way of marking component as compatible with shallow equality checks, without using mixins. We'll see how and if we want to extend this behavior in some cases to functional components but it's not as straightforward as just making them behave the same.

@Andarist
Copy link
Contributor

I remember from the other discussion thread that SFC were supposed to check the nearest class parent and based on it being Pure or not should opt in the being pure themselves.

Is it the part of this release?

@gaearon
Copy link
Collaborator

gaearon commented Jul 30, 2016

No, we decided to not proceed with this because the community discussion around it was controversial. These heuristics would be far from obvious, and we feel that this is not a good time to introduce them. Maybe we’ll figure out something more explicit in the future.

@raphaguasta
Copy link

Hi @gaearon!

In the Changelog of react 15.3 (https://github.com/facebook/react/blob/v15.3.0/CHANGELOG.md), says that React.PureComponent was added, and refers this discussion. But here you said that this feature didn't was incorporated.

After all, it's in the React 15.3 or not? Is there some documentation about this?

Thanks :)

@sophiebits
Copy link
Collaborator Author

PureComponent is included; the heuristics for stateless functional components are not.

@gaearon
Copy link
Collaborator

gaearon commented Aug 23, 2016

The feature is incorporated. My comment referred specifically to the previous comment: #7195 (comment).

I remember from the other discussion thread that SFC were supposed to check the nearest class parent and based on it being Pure or not should opt in the being pure themselves.

So “heuristics” for functional components are not in, but PureComponent is.

@raphaguasta
Copy link

Great! Thanks guys! :)

@mmcgahan
Copy link

Is there a plan to add docs to https://facebook.github.io/react/docs about PureComponent?

I'm running into some unexpected SyntaxError: Unexpected token import errors when running my Jest unit tests on a component that just changed from class Avatar extends React.Component to class Avatar extends React.PureComponent - no other code was touched but I'm not sure where to tweak my configuration without reference docs.

@koba04
Copy link
Contributor

koba04 commented Aug 24, 2016

@mmcgahan #7379

@gaearon
Copy link
Collaborator

gaearon commented Aug 24, 2016

I'm running into some unexpected SyntaxError: Unexpected token import errors when running my Jest unit tests on a component that just changed from class Avatar extends React.Component to class Avatar extends React.PureComponent - no other code was touched but I'm not sure where to tweak my configuration without reference docs.

This seems like something you’d want to file with Jest.

*/
function ReactPureComponent(props, context, updater) {
// Duplicated from ReactComponent.
this.props = props;
Copy link
Contributor

Choose a reason for hiding this comment

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

it's not a duplication, right? 🍺

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.