2. good: being able to render that state from one parent, because you don't need to manage two separate statemachines (the UI and the business logic) anymore.This is one of the areas I found to be most disappointing in practice about using a data store built with an immutable state tree and then using self-contained transactions to update it, which is similar to the Redux+Immutable model.
One of my current projects is a somewhat large web application. It has relatively complicated state to maintain for a web app, with very heterogeneous data and lots of relationships and constraints to enforce between data points.
In the early days, using React for rendering was quite convenient, and using Immutable then made writing shouldComponentUpdate quick and reliable, which was necessary almost immediately to achieve acceptable performance with React. Essentially, you’re using references within the immutable data as a proxy for a “dirty” flag on each part of your state.
However, it wasn’t long before the presentation code started to depend on derived state that was expensive to recompute: temporary tables, automatic diagram layouts, etc. This is where I find the immutable data structures really lose out compared to some sort of lazy observer architecture, because you are back to having a synchronisation problem between your derived view state and your underlying data model.
You can set up your derived view state as immutable values as well, and thus keep the reasonably simple shouldComponentUpdate mechanics, but you still need to either push changes from the underlying data model or pull them from the view. In the former case, you’ve effectively given up the declarative rendering that makes React more attractive than actively updating the DOM in the first place. In the latter case, you’ve created cache invalidation problems that undermine the benefits of having a cleanly updated, immutability-based data store in the first place.
There are several other advantages that have proved to be useful with this particular combination of tools, but they do come with some nasty performance and scalability implications, and in particular, they don’t generalise and compose cleanly in the way that a good observer-based design would. Worse, I suspect the difficulty of managing derived view state efficiently is inherent to this sort of architecture, because it seems almost inevitable in any system with data complicated enough that using a separate data store and declarative view rendering is worth the performance overheads in the first place.