A Conceptual Look at Om (ClojureScript for React.js)
josf.info
josf.info
I am still, however, a big fan of the immutable/Om way of doing things with React, and it will be the way I build future React projects from the ground up.
Some feedback on the article itself:
"For an animation, like moving a <div> from left to right, the IRenderState function might be called several times a second. Sometimes it is better to think of your app like a movie (a cartoon, I guess) rather than a static set of objects sitting around waiting for events to happen. And if you are thinking: “that must be horribly slow”… well, it isn’t, thanks to React’s virtual DOM that efficiently projects changes out into the real DOM."
If you're re-rendering a div in different places using Om/React in order to animate it, I would say you're probably doing it wrong. You should do one re-render to apply a new CSS transition class.
Also, lots of re-rendering on desktop Chrome is, usually, quite fast because of V8 and desktop CPU's... try doing this on mobile, or (in our case) a DTV set-top-box, and you'll quickly run into performance issues. Not every JavaScript engine/platform is fast enough to pull off the naive "re-render everything" approach in React. That's why they included shouldComponentUpdate, and why David Nolen went to such effort to facilitate cheap shouldComponentUpdate checks in Om.
Of course, YMMV, don't optimize prematurely, but don't also assume "re-render everything and the virtual DOM will always make it fast enough".
Unless, of course, that doesn't make sense, like if you're implementing drag and drop.
It supports o(1) shouldComponentUpdate
My hn comment history has some discussion about it
I'm on my phone now but if you email me I can give more info. I've used react-cursor in two enterprise grade apps in regulated industries and couldn't imagine using react without cursors (believe me I tried)
I've enjoyed working with Reagent, which is another react clojurescript interface. It sacrifices some very minor functionality for an extreme decrease in complexity. It's actually enjoyable to make a UI with it.
[0]: https://github.com/swannodette/om#applications-built-with-om
Could someone please expand on this statement? If the purpose of the MVC separation was a separation of concerns and organization, what is the impact of their layering no longer being relevant?
Here's my take. Om's "application state" (only data) corresponds to the data part of the model ("M") in most MVC frameworks. In Om, just like ClojureScript or Clojure, you use functions, organized however you like, to work with data. This means that the "action-oriented" part of a traditional MVC model (e.g. methods in OO) are not necessarily grouped with the model data. Perhaps this is what the author is getting at: you can "layer" (organize) your functions into whatever namespaces you like.
In in my recent experience building Om apps, I've found that organization matters. As an Om app grows in size, it is natural (and important) to find ways of organizing that help. Om does not impose any particular organization scheme. I personally find ClojureScript namespaces to be very easy to work with; I simply split up a codebase as files become larger and harder to summarize.
"... it’s just that the layering of the three is no longer pre-ordained by the framework."
That is pretty close to what I think. And I don't have any great certainty about any of this. I'm not going to go around saying "MVC is dead!"
What I observe with Om is that Om works well because it determines a flow of data, and the tools that we have to influence that flow of data, which could be identified with M, V or C, don't need to have any kind of formal separation, as opposed to a framework where you would have Model objects, Controller objects and View objects. It seems to me that Om and React have shifted the metaphor a little bit, and that the MVC metaphor isn't the best one to describe what is going on.
So if you use any ClojureScript libraries in production, expect to run into strange issues and submit bug reports that are not responded to for months on end. Nothing against their authors, it's just the nature of writing niche tools.
All that said, once devs are up to speed, and designers have a modicum of tooling, it's the best system I've used so far.
Personally, I ran into an issue with the Chas Emerick's testing framework and lost about a day of dev time trying to track down the issue. I never did figure out what was wrong and ended up just scrapping and starting over. In the end, it would have been nice to have some alternatives, but there really weren't any mature ones at the time.
Contrasting the situation with a language like Python where, should I run into an issue with Py.Test, I can always switch to Nose or numerous other frameworks.
Searching for documentation for CLJS is also a bit rough. I ended up relying on ClojureDocs for the most part, but because CLJS transpiles to JS and not JVM code, there are some undocumented idiosyncrasies. This also complicates troubleshooting because the errors are thrown by something like line 6400 of the transpiled code, not line 20 of the code you have been writing.
I still love the language. I am even taking part in a CLJ/CLJS specific hackathon next weekend. However, I have trouble recommending it to others without caveats. Most of which are due to the language's relative immaturity.
Once you have these working, errors are linked to line 20 of hte code you are writing.