The reason UI programming isn't reactive is because reactive systems are immediate mode (describe the whole state at any point in time) and the Dom (hell, most UI toolkits) is retained mode (stateful). So you need to abstract that away somehow and that abstraction is guaranteed to be leaky to some degree.
The thing that separates react from the rest (disclaimer: I work on react) is that these leaks are pushed to the edge of your system (that is, you need an external signal to re render) rather than threaded throughout your system (like requiring everything to go through $scope for one). We have seen massive dev efficiency gains because this removes many limitations for not much downside.
Incidentally I was just watching one of your presentations on YouTube to understand the reasons behind React's design choices.
The thing I still can't understand is why we need to model the UI around emulation of immediate mode.
Two big reasons:
1. The fact is when you want to create a meaningful animation between one state and another, you need to be aware and in control (as a developer) of what exactly the change is. Diffing may produce one possible valid state change delta for the developer to work with, but no guarantee it'll be the correct one. So what does that mean for animated transitions? Is immediate mode dooming them to either not be used, or to be semi-arbitrary depending on what the diff engine decides?
2. Fact is that the browser usually has no access to the full server-backed state of the widget that it's rendering. Instead, the communication with the backend that powers said widget (say a chat box) is in the form of delta state changes. You don't get the full chat log from the server every time someone sends you a chat message, you get the change only: new message from x.
So if we need to be "state aware" and communicate with "state change events" so to speak with the server anyway, why suddenly drop that knowledge and pretend all the state is local by emulating immediate mode rendering?
It doesn't feel like less work. It feels like more work, and less possibilities (said animations in point 1).
Thumbing this from my phone so can't go into as much depth as normal.
1. The diff algorithm is deterministic and accepts that some widgets are stateful. You can tell the system which items to preserve and which ones to destroy by providing an identifier. This is essential complexity in the current world we live in (global dom state tied to element instances like focus). If we were to throw out the Dom spec and rebuild it we would not need to do so much.
So you can animate by tweeting a value and rerendering/diffing every frame. Facebook look back video editor works this way.
2. Yes, but delta updates are imperative mutations over time and humans are really bad at keeping track of them so we should try to isolate them as much as possible. We have a separate system that coalesces these deltas into consistent views of the world which are then passed to react. This is also the role of systems like rx.
One way to think about it is like rest. People like rest because it is predictable: URL refers to the same resource always and refreshing the page always works consistently and you never need to think about deltas.
I tend to model and see all communication (at all levels) as message passing and not as resource/state snapshot passing, but the web has worked fine with the latter concept so far. So React's architecture certainly provides value in such situations.
Totally get you on that. I think that message passing is valuable because it forces you to decouple systems in a way that reduces shared state. But for complex apps this means that you will probably have to introduce some sort of coordination system, which is where things start to get complicated. If you can pull "time" out of the equation (ie look at complete state snapshots rather than messages over time) it can make things a lot easier. Obviously not appropriate for everything, but has worked well for us when building UIs.
No problem btw, fire away if you have any more questions!
One approach to the animation issue is to use CSS transitions. This way your code is just responsible for setting the new value (which can be done by Om/React or any other approach) and then the browser is responsible for making the animation happen appropriately (and efficiently, with full hardware acceleration, etc).
This is, for example, the approach suggested by Kevin Lynagh for use with his awesome C2 library which is like D3.js for ClojureScript and which comes with no built in animation support whatsoever:
I'm not a front end developer and so I don't spend too much time on this type of stuff, but when I have had occasion to use it, I found this approach much more pleasant than oldschool jquery style approaches to animation.
The thing that separates react from the rest (disclaimer: I work on react) is that these leaks are pushed to the edge of your system (that is, you need an external signal to re render) rather than threaded throughout your system (like requiring everything to go through $scope for one). We have seen massive dev efficiency gains because this removes many limitations for not much downside.