Reactive MVC and the Virtual DOM
futurice.com
futurice.com
Practically every desktop UI works that way (Windows API, X Windows, Java UI libs). It's funny to see how web programming in 2015 slowly reinvents the wheels known since 1970s.
So it's kinda funny that the modern state of web dev is adding another layer of that same approach on top of layers of that approach.
freeze()
doLotsOfUpdates()
thaw()
So one would have to reinvent this. Kind of reminds of propeties in some languages, runtimes and their UI's: someForm.setWidth(500); // And it's updated right away on the screen, instead of being deferred, or put in some freeze()/thaw() mode. (disableUpdates() / enabledUpdates()).When we modify DOM it becomes "dirty", and after our script finishes, reflow/re-render happens. But also, if our script queries DOM properties, like elem.clientHeight, DOM may need to perform the calculations in order to return us correct values, reflecting all the recent property changes. For example, if we access element.clientHeight browser may need to calculate re-flow (I recently encountered very slow clientHeight calculation by FireFox).
So, if we only modify DOM properties, all the re-rendering is deferred till the end of script.
Google about "DOM reflow"
I suppose that's the value proposition of React Native; write your javascript logic once and just rewrite the render function for Android, iOS, web, any any future target that implements the API.
It's possibly missing this "mode" because of other factors (what if you never put it back in "updates enabled" mode?)
This can definitely be disorienting since by default you use imperative APIs to create the actions, and then switch to working with events and subscribers from the dispatcher up until the re-render. I've not had too much difficulty with this, at least after some initial confusion.
> Flux dictates that inter-model dependency should live in the Dispatcher, but in MVI, those dependencies are defined inside each Model.
Maybe this should be edited. Flux stores are the analog of models, and each store can define which other stores have to finish updating before it responds to a given action (in that big case statement where it registers with the dispatcher).
The arguments for RxJS, testable view functions, and avoiding internal component state are important. The dispatcher being a singleton doesn't seem to affect much in practice, since that code is never really touched. Looks like performance could be better with virtual-dom but I'd be interested to see the different optimization strategies for each architecture and how they affect performance. Some of my own notes about optimizing React/Flux are here if you're curious: http://guscost.com/2015/05/27/react-js-and-flux-ideas-for-pr...
Also I think that reusable components is a really nice feature and I would encourage you to continue working on including this functionality. All in all a very nice piece, thanks for writing it up.
Everything else was just less convincing. The real power of React is composable components that are easy to think about. I don't think the author really "got" this; if he was building "complex state machines ... and [mixing] multiple concerns in one component", he was just doing it wrong.
I also don't love the idea of stores depending on each other. In my experience, it leads to hard-to-maintain tangled interdependencies, especially on the frontend. I actually tried to use Bacon.js as a Flux replacement because of the reactive philosophy (this article was a source of inspiration), and while it was nice, the purported benefits of Rx fell flat and store interdepencies remained a problem.
Now, I use NuclearJS [0] to avoid store interdependency altogether. It's actually what I was trying to build with Reactive programming, but done better.
There's a tendency in JavaScript development especially to overthink, over-engineer, and over-abstract. We're still in the middle of the woods with JavaScript application development. I hope we get out soon!
I'm not entirely convinced of the separate "renderer" or really the act of updating a virtual dom but I do like the model-view-intent. What I've done is something pretty similar though typically I combine the model and the view in all cases but the main application itself. Basically the breakdown is like this:
Application controller - initializes application components / authorization / anything necessary for startup
Web components - Either through webcomponents.org polyfills or polymer these are the individual components that make up the user interface of the web application. Each web component is entirely responsible for its interaction with the user. It subscribes to messages when it should take in updates and it emits the data the user inputs.
Application libraries - Handles the other end of messaging; has zero interaction with anything within the DOM. Subscribes to data that gets emitted from the web components and emits data that the web components need to display to the user.
I try to keep things as basic as possible. I'm still experimenting and working on an example web application using msngr.js that I can actually release as open source but I am a fan of this type of pattern. The best part of this is I can do full unit testing on the application libraries with zero DOM and the web component side of things can be fully tested with mocked results.