> Is it true that om really wants to manage the entire application state in a 
> single atom. So we might have an atom map structured with keys referencing 
> each functional area {:car-search {} :patient-search {} ...}? I understand 
> that this isn't inefficient as components receive a cursor into their bit of 
> the map thus avoiding unnecessary false changes.

Technically, each root component can only have 1 state atom, so you could in 
theory use multiple roots.  I think this ends up being pretty rare in practice, 
though.  For various reasons, most people seem to end up using a single root 
component for the whole app.
 
> The main app will have an expandable left panel containing the global menu. 
> In dom-manipulation world I would add a "collapsed" or "expanded" CSS class 
> which defined the appropriate widths etc. In om (or rather react) land this 
> is still possible I think, but is it more idiomatic to store the 
> expanded/collapsed flag in the application state thus causing the "panel" 
> component to re-render, the panel component then switching on that 
> "expanded?" flag? The "central" panel also needs to be resized in response to 
> the expansion/collapse, thus both components need to be in-sync. How is this 
> idiomatically handled?

I have that scenario in my app, and yes I just programmatically toggle those 
css classes based on the state so I can take advantage of CSS animations (which 
are hardware-accelerated on mobile platforms).

Here's a gist using Reagent:  
https://gist.github.com/mdhaney/e873611160341da79d77

These are just a few components for the menu, to show the pattern.  There are 
actually 2 menus, the off-canvas menu to the left, and from there a sub-menu 
can be selected  (I'm using Foundation for my base CSS framework, and haven't 
completed my conversion to semantic classes, which is why the components are 
still littered with presentational classes).

A few notes about how I structured this:
1.  Most components receive 2 parameters, "state" and "event".  The "state" is 
a map containing all the application state, but not in the Om sense.  Most of 
the values inside state are separate Reagent atoms, I just bundle them up to 
make the easier to pass around.  The app logic is structured into components 
that generally take the entire "state" map as their input and extract what they 
need (similar to the Component library in regular clojure).

2. Event is the core.async pub/sub channel, and "subscribe-to" is a macro to 
easily set up listener go blocks for the given event.

3. In Reagent, a component can return either its markup or a fn with the same 
parameters and that fn will be called when it needs to be rendered.  This 
allows you to setup closures for local state, and I also take advantage of this 
to just setup event handlers for the component, like in [main-menu] which has 
no local state.
  
> 
> In the more general case, there are components that need to be shown/hidden 
> (tabs, validation pop-up errors etc.). In dom-manipulation world I would set 
> css classes to change style's visibility for example, is this idiomatically 
> done through flags in the application state?
> 
Another way to do it though, is to simply render just the DOM you need for 
something like a tab view (rather than rendering all tabs and switching using a 
CSS class).   I mentioned this in your thread the other day, but as a general 
rule what I do is use the CSS classes if I need to take advantage of animations 
(like an off-canvas menu) and just render the actual DOM needed (based on 
flag(s) in application state) for things like tabs, main content view, etc.

With Reagent you could have an atom representing the current tab and store the 
component name in there (as a symbol) and then just reference it like any other 
component.  Whenever some part of your app updates that state, then it will 
automatically be re-rendered.  I'm not sure if that makes sense, but he does 
that in the routing example I linked to in my previous response.

> I am stumped as to how routing navigation fits into something like om. Again, 
> is it a case that the navigation handlers simply update the application 
> state? (You can see a theme in my thinking here!)

Your thinking appears to be on track in that in general, you modify app state 
and then your UI components are just a pure functional transformation from that 
app state to React's virtual DOM.

> 
> In terms of reagent is it true to say that it is a bit less opinionated about 
> these things and where-as om has a very opinionated approach to front-end 
> state management (happening to use om), reagent is a (very nice) wrapper to 
> om? Not to trivialize reagent, but is is "simply" trying to introduce 
> clojurescript to react?

Addressed this in my previous reply.

> Is it also true to say that whilst om wants to manage the whole application, 
> reagent allows you to think about disconnected bits of your app?

Yes, and that's why I like the Reagent approach better - I can modularize and 
reason about different functional areas.  Even if I choose to bundle up all the 
atoms together into a map to make them easier to pass around, like I showed in 
my gist, I still have that choice and can develop each logical component 
separately without them having to know about each other or how they mix 
together in the overall app state.  During app startup, I explicitly gather and 
initialize the components I am using for that app.

> 
> FWIW - reagent appeals to my pragmatic "need to get stuff done" and it feels 
> very un-opinionated and very lightweight. However, the more I read about om 
> the more it jives with me. However, I am in the pattern of "yeah, that is how 
> I would solve that problem", I just can't quite connect the dots in the 
> bigger picture. 
> 
It sounds like you're where I was before I really dug in and tried Reagent - 
"yeah, it looks easy, but it's probably TOO easy and I'll paint myself into a 
corner and regret it halfway through the project".  I have not found that to be 
the case at all.

-- 
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 clojurescript+unsubscr...@googlegroups.com.
To post to this group, send email to clojurescript@googlegroups.com.
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to