Can we improve react.addons.update then? Mori is not syntax compatible with javascript datastructures, and needs to be marshalled to interop with javascript components. If you include marshalling overhead, mori is in the same ballpark as react.addons.update.
The reason why Mori scales better is because it implements arrays via a tree of 32-slot arrays. So unfortunately, you cannot use normal JavaScript data structures and have to re-implement all the array methods that know how to deal with this data structure.
React.addons.update uses normal JavaScript arrays. So it won't scale as well, but at least you get immutability.
If your react state contains large lists, I think React's render() is going to be the bottleneck, not javascript arrays. That's why react state needs to be structured in a tree, so you can implement shouldComponentUpdate and get O(log n) renders. I wrote more in reply to jlongster.
That's the thing I love about React though; you don't have to marshal if you embrace mori wholesale. I can render components based on these data structures and never have to "reify" them into real JS data structures.
That said, I'm probably being overly optimistic and I'm just starting to research it. I don't quite like how addons.update feels like a bandaid, but maybe it is good enough. Haven't done enough research yet. I definitely don't like writing updates the way addons.update forces you to, but sweet.js macros could solve that (and I was going to write macros for mori anyway).
I've done some research too - check out this implementation of cursors, it enables drop-in O(1) shouldComponentUpdate (like Om) and is compatible with rAF batching (like Om). We explored Mori for a bit too and ended up deciding Mori wasn't worth it. (Our app was big enough that we experienced pretty brutal performance without shouldComponentUpdate. Now our bottleneck is methods like Array.prototype.map over large lists in render, which Mori can't help with - we have to restructure our state away from lists and into trees to better take advantage of shouldComponentUpdate)
(It is backed by react.addons.update, it provides a mechanism like mori.assoc_in for immutable subtree updates, and it preserves reference equality for equivalent cursors (value/onChange tuples))
Very cool! I had researched this technique before, when I found cortex: https://github.com/mquan/cortex. Cortex does something very similar, except it doesn't actually do persistent data structures. Building cursors off of the addons.update stuff is a neat idea. (why `onChange` instead of `set` and `pendingValue` instead of just `value`?)
I agree that you can take this really far. At this point I need to sit back and thing about it. :) I think mori could provide better performance for certain types of apps, but it does come at a cost if interop. Time to hit the hammock.
Hm, Cortex looks almost like my Avers (https://github.com/wereHamster/avers). With the major difference that Avers uses Object.observe instead of explicit setters/getters, and Avers mutates data in-place. I also use it with react, and haven't noticed any performance issues. But I have an idea how to make it work with immutable data (to allow === comparison in shouldComponentUpdate).
We chose cursor.value and cursor.onChange to line up directly with react's value/onChange convention. But, we are considering a nomenclanture change and we will probably expose all the react.addons.update - set, merge, push etc. Knowing when to choose value vs pendingValue() is essential complexity, but cursors make it a mechanical decision - in a lifecycle method? use `value`, in an event handler? use `pendingValue()`.
I know you've probably answered this question a million times... but could you briefly explain your enthusiasm for clojurescript and/or om? I've been using the react js library and have been wondering what makes clojurescript a step above javascript and om a step above react.
http://jsperf.com/sprout-vs-mori/3