It does make sense because init-state is run, then the first render happens, THEN the transaction from init-state is run and changes the app state, triggering a re-render.
I did find this problematic in some code where I wanted an editor component to support both editing the current value in the app state and also resetting it to a new "blank" state, but when choosing new, it would render the non-blank state first and then rerender with the blank state, instead of only the blank state. The solution is, of course, to initialise the app state in the parent when calling build (either by passing in a modified cursor, or using :state or :fn options). I find that in cases like my editor example, this breaks encapsulation (but does give you a lot of flexibility by decoupling managing state from using state). Two options would be to either wrap the component in another "state manager" component, or to wrap calls to build to make component-specific build functions (eg build-my-widget would call om/build and correctly set up the state/opts etc). David - I see that om-sync uses an "invisible" component. Its my understanding that using invisible components to manage state is how you expect state to be accessed by "external" things, as in om-sync, but how expensive are they for internal things where other solutions (like wrapping build) also exist? IE which, in your opinion, should be the preferred approach? On 21 April 2014 11:44, David Nolen <[email protected]> wrote: > Oops, sorry I read this too quickly. Yes this is the expected behavior and > not an issue at all. > > David > > > On Mon, Apr 21, 2014 at 3:44 AM, Sven Richter <[email protected]>wrote: > >> Hi, >> >> while exploring OM I found out that render-state is called twice if >> "init-state" changes the app-state. >> This small snippet demonstrates this effect: >> >> (def app-state (atom {:releases []})) >> >> (defn div-list [data owner opts] >> (reify >> om/IInitState >> (init-state [_] >> (println "init state") >> (swap! app-state assoc-in [:releases] "res")) >> ;)})) >> om/IRenderState >> (render-state [_ _] >> (println data) >> (dom/div nil "release div")) >> )) >> >> (om/root div-list app-state {:target (gdom/getElement "elem")}) >> >> First "init state" is printed, then the empty "app-state" atom and then >> the "app-state" atom with the new data. >> >> Thinking about it I guess it's correct that render-state is executed >> twice, first on initialization and then after the change of the app-state. >> However I guess it would make sense too if render-state is executed only >> once, because it should be registered, after init-state was executed once. >> >> So is this expected behavior I am seeing? >> Btw. I use om 0.5.0. >> >> Best Regards, >> Sven >> >> -- >> 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 [email protected]. >> To post to this group, send email to [email protected]. >> Visit this group at http://groups.google.com/group/clojurescript. >> > > -- > 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 [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/clojurescript. > -- 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 [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/clojurescript.
