Hacker News new | past | comments | ask | show | jobs | submit login

> So all you have to do is use PureComponent everywhere and you’re good to go. There’s nothing more to it. Enjoy your new blazing fast React app!

(I work on React.) This isn't quite right. If we recommended that PureComponent be used everywhere, it would probably be the default already. Rather -- the comparison to decide whether or not a component should be rerendered costs something, and in the case that you do want to rerender, all of the time spent checking whether you should have rerendered is wasted.

Instead, we'd suggest you be conscious of where you need to do the comparisons. It's usually only in a couple of places in your app. Good candidates are on the children of a long list or around large parts of the app that change independently (that is, cases where you know the parent should often rerender but the child shouldn't). A few well-placed shouldComponentUpdate (or PureComponent) uses can go a long way.




Hi Ben! At the React conference, I asked Sebastian Markbåge (also a React author) why `PureComponent` wasn't the default and he said there were already too many new concepts when React was released, and it would have made adoption harder. But he implied that maybe it should be the default. (Then again, alcohol was involved so I could be misremembering.)

When using immutable data structures the comparison in `shouldComponentUpdate` is very cheap. Assuming that, using pure components everywhere is very tempting for simplicity.

Correct me if I'm wrong, but React creates an object for every component to pass props around. Constructing that object is linear in the number of props. An additional `shouldComponentUpdate` check for each component is also linear in the number of props. So using pure components everywhere is at worst adjusting the constant.

Also, in a world where PureComponent is the default, perhaps React could monitor the "hit rate" of `shouldComponentUpdate` and decide to not call it if a component returns true too often?


> When using immutable data structures the comparison in `shouldComponentUpdate` is very cheap. Assuming that, using pure components everywhere is very tempting for simplicity.

PureComponent always uses === on each prop value (regardless of type), so the comparison cost with PureComponent should be relatively flat regardless of whether you're using (persistent) immutable data structures. There's also a cost in looping over the prop values and indexing into the (megamorphic) hash map for each props object that is harder to quantify.

> React creates an object for every component to pass props around. Constructing that object is linear in the number of props. An additional `shouldComponentUpdate` check for each component is also linear in the number of props. So using pure components everywhere is at worst adjusting the constant.

That's true. We've just been a little wary of ending up in a "death by a thousand cuts" scenario where every single unnecessary PureComponent makes your app a little bit slower. A number of teams at Facebook have also chosen to use PureComponent for most use cases so you're not alone.

> Also, in a world where PureComponent is the default, perhaps React could monitor the "hit rate" of `shouldComponentUpdate` and decide to not call it if a component returns true too often?

That would be cool, doing a sort of "profile-guided optimization" for React trees. I don't think this would be feasible to give improvements at a per-user/per-session level but could potentially give significant wins if you had a way to collect stats across many different users.


I've updated the post to say 'in the right places' instead of 'everywhere' until we get some profiling data.


> When using immutable data structures the comparison in `shouldComponentUpdate` is very cheap.

The equality check is always the same in pure components. Whether the data is immutable or not, pure components do a reference equality check. This will result in failing to update correctly with mutable data.

For simplicity, I guess you could go with PureComponent by default, and remove it as an optimization instead, which is what I've been doing with good results.


First off, thanks for your work on React! Makes all of our lives easier as developers :)

As dmnd pointed out, I'm not entirely convinced that dropping PureComponent everywhere is not a good idea.

For our app specifically, we unfortunately do data loading in a lot of places, which means that there are quite a bit more than just few places that can benefit from being a PureComponent. Our current idea is to try to make everything a PureComponent, and go back and 'unpurify' the places that have wasteful sCU comparisons. This might not turn out to be a good idea though, for the reasons you mentioned.

I'll make sure to do some profiling in our codebase once we get to that point, and see how much wasted sCU we are doing.


If the data structure is immutable, such that it's either a pointer comparison or "check until first part of the data is different", isn't it faster than render + diff anyway?


How do function(al?) components compare in performance to PureComponents?

e.g.,

    const MyComponent = props => (...);
vs

    class MyComponent extends PureComponent {...}


A functional component is not pure, it's exactly the same as its class counterpart. You can use recompose's[0] 'pure' HOC to turn it into a PureComponent.

[0] https://github.com/acdlite/recompose


I believe their question is asking about the trade-offs of a PureComponent, which is a Class and incurs a performance hit because of that versus a functional component which is always faster than the equivalent component written in a Class-y syntax.

I.e., do the gains from PureComponent exceed the cost of a Class? Personally I would assume they would otherwise no one would ever think of think using one, but it is an interesting question and set of metrics that could be gathered.


Not sure I understand your question. Functional components and class components both use createClass internally IIRC. In any case, they are the same. A PureComponent is simply a Component with shouldComponentUpdate written for you. Functional components can't be pure, but you can use an enhancer for them.


Is it considered best practice to use the "key" of a child element to signify if it should rerender? This is what I've been doing and it seems to work well. If a parent updates its state, and then as a result, changes the props of some or all of its children, the parent sets the "key" of a child to effectively a hash of the props of that child.


I believe it's best practice to set the key to be something that is based on the identity of the component to be rendered.

The idea is that this is used to suggest whether when rendering a component, the children are new components, or simply existing components with updated props.

E.g. You have a component that renders a list of items. If you add an item, what you would rather do is create a single new child component and re-use the previously generated children vs. discarding the child components from a the previous render and creating a brand new set.

If you create a key based on a hash of the props this will decrease the time taken to re-render an set of child components with identical props, but at the cost of discarding an existing component and creating a new one if one of the props changes.

Or something like that.....

See for a bit more detail: https://facebook.github.io/react/docs/reconciliation.html


I don't know the internal details but that sort of abuse of the key attribute seems like a dangerous thing to rely on.

I'll assume your key is quick to calculate. If a prop change causes the hash / key to change then react doesn't know how to reuse the dom fragment. I guess it will just reuse the stuff that's in the same location in that case so maybe it's fine. You'll lose the advantage that keys give you in the first case which is dealing with reordering.

And actually, just because the key changes or not, that doesn't cause a rerender or not. The rerender is always going to happen. Right? Unless I'm missing something.


keep in mind that changing the key will completely destroy and create a new element- a more expensive operation if all that's necessary is changing the class or something


nit: new component instance (not element)


I think we're both right- I believe it will create a new element and a new DOM element, rather than mutating the existing ones.


You're right. I misinterpreted your first comment to refer be referring to React elements, which is quite different from DOM elements https://facebook.github.io/react/blog/2015/12/18/react-compo...


> If we recommended that PureComponent be used everywhere, it would probably be the default already.

> Instead, we'd suggest you be conscious of where you need to do the comparisons.

I'm not following, wouldn't that mean PureComponent by default and opt-in specialized checks when needed?


No, because PureComponent does have a check.

His point is that you don't always need that check - that check has overhead too!

Basically PureComponent is just a specialized case of shouldComponentUpdate so it's better practice to be mindful of where you're calling that anyhow.

It's also why there's the push to use stateless functions (when you can) because the kind of pseudo micro-optimization that PureComponent actually is can have counter-intuitive consequences.


Hey Ben! Could you speak to using stateless functional components vs PureComponent in terms of performance, especially now that Fiber is close? Which one would you use today?


how expensive are shallow === checks compared to re-rendering unnecessarily though? what advantages would stateless functional components offer above purecomponents?


If your check returned true, you'll re-render anyway, so time for this check is effectively wasted. Imagine that every check returns true. It's better to avoid this check at all in that component.


to clarify, i meant stateless functional components after they've been optimized in React 16


Literally the next section is "*Except…", so might want to continue reading the article before leaving your comment here


Hi! I did read the whole article and don't believe it addresses the point that I called out in my comment. I hope you'll agree after reading the article and my comment carefully.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: