[ANN] reagent-forms a simple data binding library for Reagent

1,140 views
Skip to first unread message

Dmitri Sotnikov

unread,
Sep 8, 2014, 6:05:31 PM9/8/14
to clojur...@googlegroups.com
The goal of the library is to automate the process of binding form elements to a document represented by a map in a Reagent atom.

https://github.com/yogthos/reagent-forms

Feedback and contributions are welcome. :)

Sean Corfield

unread,
Sep 8, 2014, 8:01:56 PM9/8/14
to clojur...@googlegroups.com
That looks great Dmitri! We've just made the switch from Om/Sablono to Reagent so this will be very handy for us I expect.

Sean
signature.asc

Dmitri Sotnikov

unread,
Sep 8, 2014, 10:44:15 PM9/8/14
to clojur...@googlegroups.com
Glad to hear it. I've been dogfooding it myself, but there are still a few rough edges like poor error reporting. Also, for got to mention it in the original post, but there's a live demo available here http://yogthos.github.io/reagent-forms-example.html

Daniel Kersten

unread,
Sep 9, 2014, 3:52:01 AM9/9/14
to clojur...@googlegroups.com

My apologies for an off topic post in this thread - we can take it off list or to a separate thread if it needs more than a simple reply - especially since the library looks really good!

Sean could you write a little about why you switched away from Om?

I'm just trying to get a better understanding of what pros and cons Om and Reagent have and why Reagent is a better fit for your specific use case.  I've seen a few people switching lately so I'm interested in hearing people's thoughts.

Paul Butcher

unread,
Sep 9, 2014, 12:38:02 PM9/9/14
to Daniel Kersten, clojur...@googlegroups.com

On 9 September 2014 at 08:52:01, Daniel Kersten (dker...@gmail.com) wrote:

I'm just trying to get a better understanding of what pros and cons Om and Reagent have and why Reagent is a better fit for your specific use case.  I've seen a few people switching lately so I'm interested in hearing people's thoughts.


I've written a couple of production systems using Reagent. I've not written any with Om, but have played with it quite a bit while evaluating it.

The reason why I decided to go with Reagent is code readability - I find it much easier to read. This is particularly relevant as many of the developers working on the code are new to Clojure/ClojureScript and my view was that they would find it much easier to understand Reagent than Om.

--
paul.butcher->msgCount++

Silverstone, Brands Hatch, Donington Park...
Who says I have a one track mind?

http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
Skype: paulrabutcher

Author of Seven Concurrency Models in Seven Weeks: When Threads Unravel

Sean Corfield

unread,
Sep 9, 2014, 2:18:13 PM9/9/14
to clojur...@googlegroups.com
Switching the subject, but keeping the thread. Apologies to those whose email readers may get confused... :)

On Sep 9, 2014, at 9:37 AM, Paul Butcher <pa...@paulbutcher.com> wrote:

On 9 September 2014 at 08:52:01, Daniel Kersten (dker...@gmail.com) wrote:

I'm just trying to get a better understanding of what pros and cons Om and Reagent have and why Reagent is a better fit for your specific use case.  I've seen a few people switching lately so I'm interested in hearing people's thoughts.

I've written a couple of production systems using Reagent. I've not written any with Om, but have played with it quite a bit while evaluating it.

The reason why I decided to go with Reagent is code readability - I find it much easier to read. This is particularly relevant as many of the developers working on the code are new to Clojure/ClojureScript and my view was that they would find it much easier to understand Reagent than Om.

This is essentially why we switched too. Learning Om was extremely valuable in understanding the React.js "model" of thinking but it felt very "OOP" in style and, the bigger our app got, the more that bothered me, along with the boilerplate of `reify` and `om/IWhatever` and then the method definitions. It was still Clojure but it was starting to feel like Java at times, especially with the very explicit "constructor" and local state idioms - and the various state mutation functions.

The component signatures also felt a bit rigid, always passing some state, the React node, and the optional `opts` map, so component dependencies had to be shoehorned into that structure. There were also times when it became cumbersome to communicate between components (I know David is aware of this and working on improvements). Om is very structured and quite opinionated about "how to write your app" and seems to "strongly encourage" use of channels and core.async when passing data or a simple callback might be a simpler approach, if it was possible (and it might be - I just felt I was fighting with Om sometimes trying to achieve some of this).

The DOM stuff was also a bit frustrating so I'd started to move over to using Sablono to get that familiar feeling from Hiccup, but as you can see in my early Om/Sente example code, I was mixing and matching the `(dom/tag ...)` and `(html [:tag ...])` styles from both libraries and that felt a bit clumsy (a mix of Sablono and `om/build` in `secured-application` seemed inconsistent - whereas pure `dom/div` / `om/build` in `application` felt more consistent but a bit ugly):


Of course that's all very subjective, but Reagent's Hiccup-style (component) "functions return data structures" approach seemed more consistent, more streamlined / simpler, and more flexible since it was "just functions" (and closures over state) so you could pass whatever arguments you wanted / needed. That meant one library (Reagent) instead of two (Om + Sablono) so less worry about version incompatibilities etc. On the downside for Reagent, there's a lot more "magic" in terms of how rendering is triggered based on Reagent's "magic atom" and by simplifying the main line use case (rendering, and using closures for initialization), you have the added complexity of wrapping components in metadata to hook into the other React.js lifecycle methods. It's also less widely used so there are fewer blog posts and articles about it and far fewer folks on IRC to ask questions of and bounce ideas off.

At a recent San Francisco ClojureScript meetup, some folks recounted their experiences building production apps with Om and various other frameworks which I think makes interesting reading (I couldn't attend unfortunately so I was very grateful that Peter took detailed notes!):


There are definitely things to love about Om. It's well-documented and there are plenty of examples and blog posts about it. There's a growing community of libraries and tooling being built up around it too. The structure and organization means components are fairly homogeneous in approach which means consistency as well as a fairly straightforward mapping between React.js and your cljs code. Cursors are great! (so much so that I submitted a PR to Reagent to add cursor-like functionality)

And finally, if it wasn't for Om, we almost certainly wouldn't be embarking on our ClojureScript journey for (internal) applications at World Singles: everything else we'd looked at before seemed to be a heap of JS interop, built on top of JS frameworks, which hadn't been enough to tempt us away from pure JS front ends...

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)



signature.asc

Daniel Kersten

unread,
Sep 10, 2014, 5:34:55 AM9/10/14
to clojur...@googlegroups.com
Thanks for the detailed response, Sean. Interesting and good points.

I've seen Peters notes and my initial thoughts were that half of the "Bad" points can be easily solved using om-tools and the other half by adhering to a strict separation between domain state (the what - stuff you'd store in a database) and transient state (the how - stuff that tells your app how to display the domain state), storing the former in app state and the latter in component local state. From what I've read, this is what Facebook do with their Flux-based code too.

There's no doubt that Om is very OOP (perhaps even a bit uncomfortably so, for Clojure), so I guess perhaps at the end of the day it comes down to how much OOP you're happy with allowing. For me, I don't mind it for the GUI code and my actual logic is very functional in style. Reagent definitely appears to be more functional style, though, which is definitely nice.

I haven't tried Reagent myself, which is why I'm interested in hearing peoples experiences - especially if they've used both Om and Reagent. Maybe I can find some time to play around with it soon.

Jamie Orchard-Hays

unread,
Sep 10, 2014, 11:40:13 AM9/10/14
to clojur...@googlegroups.com
I'm curious as well. I started with Reagent, but switched to Om/Sablono after finding Reagent's app data handling too limited for what I needed. The trade-off is much more to think about (complexity) when writing Om components. 

Jamie

--
Note that posts from new members are moderated - please be patient with your first post.
---
You received this message because you are subscribed to the Google Groups "ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojurescrip...@googlegroups.com.
To post to this group, send email to clojur...@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Dmitri Sotnikov

unread,
Sep 10, 2014, 10:11:20 PM9/10/14
to clojur...@googlegroups.com
I actually found Reagent's data handling to be very flexible. It' makes it easy to create local states for components as well as managing the global state using a global state atom. I'd be curious to hear what limitations others have run into and how they could be addressed.

Jamie Orchard-Hays

unread,
Sep 11, 2014, 2:01:59 PM9/11/14
to clojur...@googlegroups.com
On my project, I was using data in the form of a recursive tree--an editable one. I got stuck somewhere WRT to this in Reagent. (I wrote a question to the original developer, but he never replied.) For my purposes, Om's cursors made handling data updates trivial, so it was a big win. However, I'm sure I've put a lot more man hours in the UI development with Om than I would have with Reagent.

So in the end, the fact that I had a recursive tree of data to work with gave Om the edge, otherwise I would have used Reagent.

I also had a look at Quiescent, but it was too thin a layer over React for what I'm doing.

Ideally, we'd have Reagent's UI simplicity combined with Om's wonderful app data handling.

Jamie

Sean Grove

unread,
Sep 11, 2014, 2:34:25 PM9/11/14
to clojur...@googlegroups.com
Bit of a sidenote, but now that the libraries are getting more mature, It'd be great to see some complex-ish apps (say, Omchaya-size or larger, but maybe even CircleCI's frontend https://github.com/circleci/frontend) for a side-by-side comparison + speed benchmarks, to get a sense of the tradeoffs as apps scale out. I'm personally curious about whether Reagent's ease of use comes with a cost at some point.

Dmitri Sotnikov

unread,
Sep 11, 2014, 4:31:36 PM9/11/14
to clojur...@googlegroups.com
So, good news is that Sean just submitted a patch for Reagent cursors a few days ago. Hopefully, that will make it into the next release.

In terms of performance I would actually expect Reagent to behave better than Om since it doesn't force everything into a single state atom. Reagent allows easily creating local states and that makes it much easier to control what nodes need to be recalculated.

If I understand it correctly, the worst case for Reagent where you use a single state atom for everything is the normal case for Om.

Daniel Kersten

unread,
Sep 12, 2014, 5:10:14 AM9/12/14
to clojur...@googlegroups.com
Note that you can have multiple roots in Om (I assume in Reagent too), each with their own state atom.

Jamie Orchard-Hays

unread,
Sep 12, 2014, 12:11:09 PM9/12/14
to clojur...@googlegroups.com
I'm pondering the implications of your comments, Dmitri. In Om, I have a single atom for my application data, but I have another atom that holds static data I pull from the server, for example lists for drop-down select lists. WRT local state, each Om component can have its own local state completely separate from the app data.

Wei Hsu

unread,
Sep 12, 2014, 3:43:40 PM9/12/14
to clojur...@googlegroups.com
Re: Sean Grove, here's a T-shirt editor app I built with Reagent. It's a bit more complex than the given examples and might help with comparisons between other frameworks.

https://github.com/yayitswei/t-edit

I'd also appreciate any feedback on the code from anyone who gets a chance to browse through it. In particular, I think the text field binding could have been implemented more elegantly, so I'm looking forward to trying out reagent-forms.

Dmitri Sotnikov

unread,
Sep 12, 2014, 4:02:04 PM9/12/14
to clojur...@googlegroups.com
This might simply be my own lack of familiarity with the Om workflow. The impression I got was that most state should live in a global atom that you create cursors into and communication between components should happen using core.async channels.

Daniel Kersten

unread,
Sep 13, 2014, 6:32:58 AM9/13/14
to clojur...@googlegroups.com

Dmitri, I would say that all of the donain data - that is, data that you might persist in a database - should be stored in the app state atom, but all temporary data about how to display the domain data (what page are you on, what tab is visible, is the button pressed, how much of a list is being shown, etc etc) should be in component local state.

From what I've read, this is also how Facebook do things with their flux architecture.

I started writing Om by storing everything in the one atom (I think the natural tendency is to do that) but I think you quickly realise that it's unwieldy (as you and others have asserted). Because it is! Then you transition to a model where the data you are operating on is separated from the incidental data and everything becomes much nicer and easier.

Dmitri Sotnikov

unread,
Sep 13, 2014, 10:32:01 AM9/13/14
to clojur...@googlegroups.com
That sounds very similar to the Reagent model then. I found that it was the natural approach there, since creating local component states is straight forward and it makes them readily reusable. This simply wasn't clear to me when I tried using Om and I found that the additional complexity that Om introduced was completely incidental to the applications I was writing.

Daniel Kersten

unread,
Sep 13, 2014, 1:22:31 PM9/13/14
to clojur...@googlegroups.com

It sounds like Reafent naturally encourages this model while with Om there's a tendency to put everything into one atom - until you learn through experience at least!

Dmitri Sotnikov

unread,
Sep 13, 2014, 1:26:12 PM9/13/14
to clojur...@googlegroups.com
At the end of the day, anything you can do with one you can also do with the other. I think the appeal of Reagent, as others have pointed out, is that it leads to much shorter and cleaner code by providing a simpler and more focused API.

On Saturday, September 13, 2014 1:22:31 PM UTC-4, Daniel Kersten wrote:
> It sounds like Reafent naturally encourages this model while with Om there's a tendency to put everything into one atom - until you learn through experience at least!
>

Matt Ho

unread,
Sep 14, 2014, 1:12:55 PM9/14/14
to clojur...@googlegroups.com
As someone else who's making the switch from om to reagent, I have to agree with what folks are saying. It's cleaner and easier to wrap your head around reagent than om. After having read the om tutorial many times, I found a single walkthru of http://holmsand.github.io/reagent/ and I was off to the races.

M

Gary Trakhman

unread,
Sep 14, 2014, 3:18:21 PM9/14/14
to clojur...@googlegroups.com
I can get things done with Om + sablono but I'd be interested to understand the tradeoffs in more detail.

But it does look like Om is more low-level than Reagent to me.

Daniel Kersten

unread,
Sep 15, 2014, 7:16:03 AM9/15/14
to clojur...@googlegroups.com
So what it really comes down to (for me, at least) is what approaches the API's encourage.

Reagent seems to encourage you to do what I would say is the "right way" (separation of state) from the start, where Om (unintentionally perhaps) encourages you to put everything in one atom, so you have to learn not to do that. But on the flipside it gives powerful state management tools out of the box that you need to provide yourself with Reagent (my instinct is that something like DataScript is a perfect fit!)

Overall, it looks like Reagent has a more pure-functional feel while Om has an OO feel, although the render function is actually pure functional (you shouldn't directly set state from it!).

Sorry again for derailing your announcement tread, Dmitri! :-(

Thanks everyone for chiming in! Its good to get a better understanding of the ecosystem and what everything is good or not so good at!

Dmitri Sotnikov

unread,
Sep 15, 2014, 7:50:52 AM9/15/14
to clojur...@googlegroups.com
Daniel, I think this turned out to be a great discussion, so I'm glad you've derailed it. It's very interesting to read others perspective on Om and Reagent and their respective benefits. :)
> >...

Reply all
Reply to author
Forward
0 new messages