Thanks for this post! I'm very inexperienced with Clojure, but I'm a big fan of React. I've always wanted to understand how Om encourages immutability and how it deals with "UIs are stateful by definition", but I never managed to wrap my head around it, probably due to my missing Clojure skills.<p>Your post explained it in general terms. I will probably apply the same in plain JS now. It sounds like an interesting challenge to implement the Cursors idea using React's Update addon [1] instead of depending on Mori. (I don't like Mori because I don't get the feeling that it's intended to be used without ClojureScript - its API is rather cumbersome from plain JS)<p>[1] <a href="http://facebook.github.io/react/docs/update.html" rel="nofollow">http://facebook.github.io/react/docs/update.html</a>
fwiw it's possible to achieve all of these benefits in vanilla react using javacsript with regular javascript data structures<p><pre><code> * single mutable ref to normalized app state
* cursors for encapsulation and modularity
* O(1) deep equality checks
* fastest possible react performance
</code></pre>
source: I have done it in two large react apps, but i have not documented it yet. Blog post coming soon.<p>Interestingly, as your app state gets bigger, you are actually forced to use something like cursors for all state updates, for performance reasons. Naive immutability in javascript means clone-before-modify, which is far too slow when your state values are large. It quickly bubbled up in our profiler. Funneling all immutable updates through a cursor means the cursor can use structure sharing on the state value, skipping the defensive clone and preserving reference equality for equal subtrees. Also afaik, implementing a general shouldComponentUpdate (edit: in js) without something like cursors is not possible, because you need === equality for onChange props.
I've had the same experience building <a href="http://fitsmeapp.com" rel="nofollow">http://fitsmeapp.com</a> with Om/Clojure -- great to see real, production apps being built in CLJS!
For people who have wanted to try this type of programming out but have not jumped the boat from JavaScript to ClojureScript, I created a little library that mixes Backbone and React in a similar model described in the article: <a href="https://github.com/andrejewski/reactbone" rel="nofollow">https://github.com/andrejewski/reactbone</a><p>It takes away a lot of the data-binding cruft that you find in Backbone.View and works well with React without making you switch languages, design paradigms, or add new libraries. The Backbone component makes it easier to build data hierarchies than with plain JS, but I assume other MVC frameworks could be retrofitted to work with React.
It's going to be much nicer when ClojureScript runs in Node without needing a JVM. Now a ClojureScript project requires a lot of boilerplate and running cljsbuild auto. For big projects this is fine but I want to write smaller scripts in ClojureScript as well. Basically I want to do:<p><pre><code> cljsbuild app.cljs > app.js
</code></pre>
And that's all. No project.clj, no waiting 5 seconds for clojure/jvm to load and Closure to compile it all.
I'm real curious about the potential interplay between core.async and om/react. Bruce Hauman has a great tutorial on using core.async channels (as opposed to event callbacks) to process user input and gestures.[1] David Nolen (creator of Om) also covered core.async.[2] But these tutorials pre-date Om; core.async came to clojurescript in summer 2013, Om wasn't released until 2014.<p>I guess the way React handles input is by attaching event handlers to child components, so that changes to the child properties bubble up to the root component state. Is this the optimal pattern for handling events in a React app? Or is there an advantage to be gained by using core.async channels to process event input for Om/react?<p>I haven't seen any examples which use both core.async <i>and</i> Om/react, but I'm very curious about the possibility.<p>1. <a href="http://rigsomelight.com/2013/07/18/clojurescript-core-async-todos.html" rel="nofollow">http://rigsomelight.com/2013/07/18/clojurescript-core-async-...</a><p>2. <a href="http://swannodette.github.io/2013/07/12/communicating-sequential-processes/" rel="nofollow">http://swannodette.github.io/2013/07/12/communicating-sequen...</a>
One thing that's unclear to me: does this require the entire application state to be loaded into memory all the time?<p>If your application state is large but you only care about a few parts of it at a time (a few "cursors") how does Om deal with that?
I'm interested in knowing more about how people are architecturing their Om projects<p>e.g. are you using something like:<p>app component <-> page components <-> (widget) components<p>where the app creates the page and the page creates the widgets and communication is flowing through channels?<p>and how do you deal with url transitions?<p>do you capture and flow up the click from a widget back to the app so it knows it's time to render a different page? and have some (case ...) at the app level?<p>or using some kind of mix with secretary and changing the location.href/a hrefs?<p>etc