jarohen / flow

Lightweight library to help you write dynamic CLJS webapps
38 stars 7 forks source link

Differences to reagent / om #9

Open sveri opened 9 years ago

sveri commented 9 years ago

Hi,

This is not really an issue but more a request for clarification if you want to. How does your library differ regarding functionality and goals from reagent and om? It would be nice to read about it in the description.

Thanks, Sven

jarohen commented 9 years ago

Hi Sven, thanks for your question :) It's probably something I should cover in the README!

Goals-wise, I'm aiming for Flow to be more lightweight - I've tried to keep as close as possible to vanilla ClojureScript + Hiccup, so that it's simpler to pick up and reason about. I'm not so worried about getting the last milliseconds of performance - certainly there are application that need this, and obviously Flow has to be fast enough to be usable, but I'd rather trade off a little performance in order to minimise the number of new concepts a user has to learn. While learning Om, in particular (Reagent to a somewhat lesser extent), I found that it introduces a number of concepts, protocols and state-handling functions seemingly as a result of being built atop React, and wondered whether developing CLJS UIs could be simpler.

The syntax is quite similar to that of Reagent (I do like the syntax!) - Hiccup is quite well-known amongst the Clojure community and has great Paredit support, so it seemed a natural choice. There are a couple of differences: I introduce a '<<' operator which behaves a lot like a 'continuous deref' - it seemed better to differentiate between the 'one-off' nature of '@' and the 'watching' behaviour of '<<'. Also, Flow uses vanilla CLJS atoms, rather than Reagent's custom atoms - I'd previously have said that this helps composability, but arguably this isn't as important since the introduction of many new CLJS protocols (e.g. ISwap, IDeref etc).

The biggest difference is probably in the implementation, particularly around DOM updates - Om and Reagent are backed by React, and so handle updates by generating a new virtual DOM, figuring out the changes and applying them. Flow components, on the other hand, can be thought of as mappings from a single state to its representation. To decide which components need to update, we look at how each component depends on the state, then calculate the changes in the state to determine which components need to be re-rendered.

Also, Flow components are 'compiled' at macro-expansion time, generating the code that creates the elements, but also the code that reacts to any changes in the state. Over time, I'm hoping to extend this to analyse the dependencies of components at compile-time so that, by the time the components are rendered, we already know the impact of a given state change, and so don't have to calculate it on the fly :)

I'm conscious that both Om and Reagent are both very popular within the ClojureScript community, and so I'm not entirely sure about the wisdom of introducing a new library to the mix - I'd be interested to hear your thoughts and suggestions!

Cheers,

James

sveri commented 9 years ago

Hi James,

Thanks for your detailed explanation. Putting this in the README surely is worth it. After reading the existing one I got the impression that flow could be a replacement for reagent / om, but was not really sure if it is or not.

Apart from that I really do like the idea to be independent of react.js and everything it requests from library code to be done. Having a pure clj/cljs solution is preferable to me too. Especially regarding future possible changes, as react.js surely is not the end to ui development.

I also tried freactive, which follows a different approach, trying to achieve similar goals, however, not being able to use nest rx elements (https://github.com/aaronc/freactive/issues/20) stopped me from using it for now.

Performance is not a deal breaker for me either, as usual, being the fastes library is most of the times not needed, developer useablity and api matters more to me :-)

Best Regards, Sven

whodidthis commented 9 years ago

I'd imagine most people being interested in how to do transition animations and server side rendering with node.js / which parts are only run in the browser (react's componentDidMount).

Looks really interesting though!

jarohen commented 9 years ago

Hi there - I'm afraid Flow doesn't support either of those as yet. I'm looking into doing server side rendering in the next major release (it's already mostly CLJX, so shouldn't be too much work), but not sure which direction to go with transition animations - I'd like to keep Flow very lightweight if possible!

Cheers,

James