I'm going to cover this in my next post, but I've found that using PureRenderMixin with fairly large number of items (~100s) works. The non-trivial step is often identifying why your subcomponents are still re-rendering, which I solved by writing a mixin that logs to the console what props/state is deep equal but not shallow equal (i.e. where PureRenderMixin should theoretically work).
But I agree, it's still not perfect. You avoid doing the more expensive virtual DOM comparison, but you still have to iterate over all the items to do the PureRenderMixin checks. And it is still O(n) time, just with a smaller constant.
Another solution is to not actually render all the children, just the ones that are visible on the screen, i.e. using some React implementation of infinite lists (see: https://facebook.github.io/fixed-data-table/ )
Another idea that I've been thinking about is to arbitrarily fragment your list into lists (possibly of fixed size, or a fixed number of fragments). Each fragment gets its own subcomponent, so we can avoid rendering fragments that haven't changed. For example, instead of a list of 100 items, we treat it as 10 lists of 10 items. If we change one item, we end up instantiating 10 components, and then recursing into the single fragment that has changed, instead of over all 100 items.
I've thought about doing the list of smaller lists but it could cause issues with the DOM (if you care about it) since components must return a single element. Will look into that fixed data table.
But I agree, it's still not perfect. You avoid doing the more expensive virtual DOM comparison, but you still have to iterate over all the items to do the PureRenderMixin checks. And it is still O(n) time, just with a smaller constant.
Another solution is to not actually render all the children, just the ones that are visible on the screen, i.e. using some React implementation of infinite lists (see: https://facebook.github.io/fixed-data-table/ )
Another idea that I've been thinking about is to arbitrarily fragment your list into lists (possibly of fixed size, or a fixed number of fragments). Each fragment gets its own subcomponent, so we can avoid rendering fragments that haven't changed. For example, instead of a list of 100 items, we treat it as 10 lists of 10 items. If we change one item, we end up instantiating 10 components, and then recursing into the single fragment that has changed, instead of over all 100 items.