Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

The PureRender and componentShouldUpdate methods are "escapes" from the React philosophy, so I don't count them as being "React". They make the code more complicated because, with them, inconsistencies can easily arise.

Making a simple local change to a list of N items, which would normally take O(1) energy, suddenly takes O(N) energy. Even with the PureRender and componentShouldUpdate methods, because React will traverse the complete list to determine which items should be changed (calling componentShouldUpdate for every item).

I agree with you on the DOM. Its speed needs to improve. React offers a nice abstraction which may keep the code simple, but, as explained here, has problems of its own.



sort by: page size:

I've done that recently, and I had many performance issues. I have a long-ish list of very simple components that are in a sorted order. So when I change the value of one, I re-sort the list. I was hoping React would only rerender the changed items (remove old, insert new). But no, it rerenders the whole list, which takes 500ms. I made sure object references in the list stay the same, that didn't help.

I can implement this thing in vanilla JS, and it would not take more than a few milliseconds. React is cool, but so damn hard to optimize.


It's a contrived example. The DOM manipulation is fast in this case because it's a simple appendChild every time. In other cases like where elements in the middle of a table are updated, you would get into a mess writing vanilla code, either complexity or performance wise, because you'd have to traverse the DOM to get to where you need to do updates and do each update individually. React batches such things together, and does one single update.

React just does the rerendering and re-binding for you - and does it way less efficient than if you hand coded it.

What you should be doing is just changing the parts that you know have changed. Letting react do the hard work will always lead to worse performance


Hardly - they enforce the React philosophy more strictly.

In an ideal system, Components receive props, modify internal state, and render idempotently based on these. The PureRender mixin is a way of saying "yes, this component conforms to the above constraints".

Unfortunately, it's not always the case that the naive way of writing a Component will comply with the PureRender restrictions, so it's not enabled by default. It's not difficult, 99% of the time, to alter a Component to work properly with only minimal changes, and they aren't changes that make the Component code more confusing.

ComponentShouldUpdate is a way of applying tree-trimming logic that React could not automatically know. Business logic and the like. When a Component implements componentShouldUpdate and returns false, it will prevent any children of that component being iterated in that loop. Ideally, componentShouldUpdate should just returning a Boolean value from state, rather than calculating it each time.


Not sure I understand your point, can you elaborate?

My point is that updating the state for a single element causes React to compute the state for the whole page, and diff the whole page virtual DOM against the whole page actual DOM, before pushing the update of that single element into the DOM. With pure JavaScript, you can skip all that and directly update a single element. This is often in practice much faster.


React reduces manual interaction with DOM (which is slow) by calculating the diff between your new render call and the previous one. Imagine building a webapp where each time you need to update the view, you just lazily refresh the whole UI. The library knows to only update the necessary parts.

In fact, the whole api is so simple that I could probably summarize the core for you:

- a `render` method that defines what the view looks like, using variables and such.

- a `setState({variableName, newValue})` call, upon which the render method is called again, but only making DOM modifications where your variable influenced them.


What I don't really get is, if you've implemented PureComponent and shouldComponentUpdate wherever possible, how can adding Immutable possibly improve performance?

The argument is that if you prevent mutation then you can rely on only a shallow comparison of the object references as a reliable test for whether any of the data has changed. Your shouldComponentUpdate implementation becomes a one-line equality test for each prop that might change, or the equivalent. This may be significantly faster (and potentially easier to maintain) than any more detailed comparison of props to decide whether anything significant has changed in shouldComponentUpdate.

Of course, this doesn't address the performance implications of maintaining your state in some sort of immutable data structures rather than just mutating it. Nor does it address the performance implications of using a library like React that declaratively renders your content and does the whole vDOM diff algorithm thing instead of just poking the DOM in exactly the required places. Both of those strategies can be orders of magnitude slower than the alternatives, and both of them can cause architectural and maintenance headaches of their own, and so the questions in those cases are whether the performance is still good enough and whether the benefits in other respects outweigh those costs.


Given that all of the code uses React.FC instead of React.PureComponent or regular React.Component the efficiency obviously lacks, there's no props diffing and everything will be rerendered.

So, you're still controlling what is updated and when, with the same potential for making mistakes that you'd get in direct DOM manipulation.

React doesn't require you to ever manually replace a component - that's why the two are not comparable.


Whenever a change is made to the raw DOM, the change has to be immediately visible to the code running after it. React sacrifices this.

When the DOM is treated as the source-of-truth for the page's information, the synchronously-visible changes are very useful. However, getting away from treating the DOM as the source-of-truth, which React forces you to do, gets you a lot of power as changes to the DOM can be batched more efficiently automatically.


It is not for small changes. But as soon has you update a whole layout of many listings, I doubt you are manually diffing your nested data structure to produce the less possible updates.

React also uses a couple of other tricks, like attaching one event handler to the top of the DOM doc and fire fake events (they call it synthetic) to avoid having many handlers in the page. Or queueing udpates and merging them so that if many updates arrive at a very close time, you update only the DOM once.

Vue.js and Angular 2 do the same. Although Vue.js is my favorite right now because it's so much more flexible and easier to use.


Disadvantage is that creating a new function on every render ruins performance optimizations like `React.PureComponent`. Although that's a pretty minor detail, (you shouldn't prematurely optimize, and sometimes PureComponent is actually more expensive than rerendering since computing whether props have changed can be more expensive than just rerendering.)

Eh, kind of. If you're rendering, for example, a Table with a lot of TableRows and change one of the values in the data array being passed to Table.props, you'd return true from Table.shouldComponentUpdate, and then each child TableRow would need to run its shouldComponentUpdate, even though only a single one really needs to update. So the argument is GP is making is that it's more efficient to directly update that single DOM element rather than update the data and then perform the calculations to determine that we need to update that single DOM element.

That's a great point, and being aware of the dangers of shouldComponentUpdate is what this post is all about. There are a lot of gotchas when using PureComponents, and can lead to bugs if you're not careful.

Also, recalculating derived data (building static lists) in render() is very wasteful, and is also another gotcha when using PureComponents (object copying). Removing object copying from render() speeds up the actual render() call and allows you to take full advantage of PureComponents.

We are experimenting with ways to make all of this a bit easier, and hopefully will have some good news to share in Part 2 :)


Try beating a loop where e.g. every time you get a change you do something like getElementById() + .textContent = newValue. There's no way for React to be faster than that because it has to eventually do the same work but there are many ways for it to be less code, more correct (e.g. by not forgetting to call the update in some cases), or otherwise easier to get to the point where your app can ship.

> sounds less efficient since you'll need to re-print the entire page with every change.

Huh? No, not at all. As far as I understand, React has algorithms that replace only the html that changed in a dom subtree (and that is called virtual dom, not shadow dom, which is a different concept).

But if you already know exactly what has changed and where to change it in the page, there is no need for more complex algorithms to kick in. Just take the pointer to your div or cell and change the content.

Bottom line: React is written in vanilla Javascript. Can't do better than it.


(a) You can use the key attribute in order to get DOM reuse. If you are looping over N keys then React is going to reuse the nodes and move them around.

(b) You can implement shouldComponentUpdate in order to have a quick way not to re-render a sub-tree if nothing changed.

(c) See (b) but we're also working on changing the internal representation of the virtual DOM to plain js objects that can be reused[1]. We were super worried about GC but it turns out that it hasn't been the bottleneck yet for our use cases.

(d) If you are writing pure React, all the actions are batched and actually, it's write-only, React almost never reads from the DOM. If you really need to read, you can do it in componentWillUpdate and write in componentDidUpdate. This will coordinate all the reads and write properly.

A really important part of React is that by default this is reasonably fast, but most importantly, when you have bottlenecks, you can improve performance without having to do drastic architecture changes.

(1) You can implement shouldComponentUpdate at specific points and get huge speedup. We've released a perf tool that tells you where are the most impactful places to[2]. If you are bold, you can go the route of using immutable data structures all over the place like Om/the elm example and you're not going to have to worry about it.

(2) At any point in time, you can skip React and go back to raw DOM operations for performance critical components. This is what Atom is doing and the rest of their UI is pure React.

[1] https://github.com/reactjs/react-future/blob/master/01%20-%2... [2] http://facebook.github.io/react/docs/perf.html#perf.printwas...


> outperforms plain React a lot of the time due to optimizations that re-render components only when their inputs change

Is this not exactly how React also works?


While the basic idea of rendering to a virtual DOM is simple, making it work well for large applications require a lot more than a toy implementation as described in the article.

In order to get adopted, React needs to coexist with existing applications/third party libraries that do manual DOM mutations. The life cycle methods are there to deal with this.

React implements its own class system that supports mixins and type annotations. The plan is to change the API to use ES6 classes (we're working to improve the standard to support all React use cases).

React re-implements its own event system in order to make it fast, memory efficient and abstract away browser differences.

Making composable components is not as straightforward as it first seems. There are a lot of edge cases like refs, owner/parent to be handled.

Then, as you mentioned, there's the diff algorithm and batching strategies which need to be implemented in a performant and memory efficient way. And provide hooks for the user to be able to give it hints via shouldComponentUpdate.

next

Legal | privacy