I try to avoid these types of generalizations.  There's nothing inherently 
wrong with "decorating" a cursor, and it will work fine in many scenarios.  But 
when you need app-state data + some other data in an event handler, you'll need 
a different approach, because deref will only return the underlying app-state 
values.


On Saturday, November 8, 2014 10:39:49 AM UTC-6, Colin Yates wrote:
> James, thank you. That does help.  My mental model of app-state being pure 
> domain and view hierarchies effectively projecting their own structures is 
> the thing to challenge.
> 
> The approach,  if I may generalise is by all means project off app-state but 
> keep it alongside (e.g. through opts as you show), rather than intermingled 
> with?
> 
> Essentially,  it all went wrong when I mutated the cursor itself.
> 
> Thanks James, 
> 
> Colin
> 
> On 8 Nov 2014 16:17, "jack james" <[email protected]> wrote:
> I don't think this is a bug. When you deref a cursor, you get the values 
> stored in the underlying app-state atom.  Here, you're storing a cursor in a 
> component's local state.  When you deref it later, you're still only going to 
> get the values stored the the cursor's underlying app-state atom...
> 
> 
> 
> A couple things:
> 
> 
> 
> 1) Storing cursors in local state is an anti-pattern.  It's one of the few 
> patterns that we've seen clear guidance on, which is: don't do it.
> 
> 
> 
> 2) In case this isn't clear: after you "decorate" a cursor with assoc, it's 
> still a cursor (with some extra stuff tagging along).  We can verify this 
> with the "type" function:
> 
> 
> 
> https://www.refheap.com/92913
> 
> 
> 
> That refheap also shows one of your options, which is to use om/value (like 
> deref, but intended for use during the render phase) to convert your cursor 
> to values, so that instead of storing a cursor in local state, you're storing 
> values.
> 
> 
> 
> That would be better, but I still don't like it.  You may be planning to 
> update your application state in your event handler with om/transact! or 
> om/update!, but those functions take cursors.  So if you've already converted 
> your cursor to values, you won't be able to use those functions. You would 
> have to update app-state with another approach (callback, channel, or 
> ref-cursor).
> 
> 
> 
> Also, remember the primary goal of react:  to minimize the complexity of 
> managing state:
> 
> 
> 
> http://facebook.github.io/react/docs/thinking-in-react.html
> 
> 
> 
> "Figure out what the absolute minimal representation of the state of your 
> application needs to be and compute everything else you need on-demand."
> 
> 
> 
> In this case, you're taking data that's already stored in app-state, and 
> storing it again in local state.  I think you want to try avoid this wherever 
> possible.  Here's one possible approach that doesn't use local state at all:
> 
> 
> 
> https://www.refheap.com/92914
> 
> 
> 
> HTH
> 
> 
> 
> 
> 
> On Saturday, November 8, 2014 7:44:51 AM UTC-6, Colin Yates wrote:
> 
> > Hi,
> 
> >
> 
> > I have found a bug, but it may well be (almost certainly is) in my 
> > understanding ;).
> 
> >
> 
> > tldr; I decorate something from app-state and store as component-state. In 
> > rendering I see the decorated thing but in on-click when I resolve the 
> > cursor I see the undecorated thing.
> 
> >
> 
> > I have a hierarchy in my app-state and a tree-component to render it. The 
> > tree component denormalises the tree so each node has an array of its 
> > parent's ids and descendant ids (for example). I then persist this 
> > decorated-tree as component state.
> 
> >
> 
> > The problem is that when I reference the decorated tree in the on-click, I 
> > can see the cursor has access to the decorated tree but when I denormalise 
> > it I see the undecorated tree.
> 
> >
> 
> > (As an aside, I originally tried it without component state and passed the 
> > decorated tree as app-state to the delegate component but that exhibited 
> > the same behaviour).
> 
> >
> 
> > I am sure I have missed something, but I don't see what - is this a bug in 
> > om? I can by-pass this by simply storing everything in app-state in the 
> > denormalised view, but that is not ideal - different components want to 
> > render the same domain chunk differently (e.g. another component might show 
> > this tree as a flattened list).
> 
> >
> 
> > The following code demonstrates the behaviour:
> 
> >
> 
> > [code]
> 
> > (defn the-component
> 
> >   [_ owner]
> 
> >   (reify
> 
> >     om/IDisplayName
> 
> >     (display-name [_] "Component")
> 
> >     om/IRenderState
> 
> >     (render-state [_ {:keys [node]}]
> 
> >       (let [{:keys [id text children meta]} node]
> 
> >         (js/console.log "NODE in rendering contains meta:"
> 
> >                         (clj->js (keys node)))
> 
> >         (html
> 
> >          [:li
> 
> >           {:key id
> 
> >            :on-click
> 
> >            (fn [e]
> 
> >              ;; prevent selection of the parent
> 
> >              (. e stopPropagation)
> 
> >              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >              ;; the cursor node contains the "meta" key if you expand
> 
> >              ;; into .value.root.arr[2]
> 
> >              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >              (js/console.log "(cursor)NODE in on-click (check 
> >.value.root.arr[2]):")
> 
> >              (js/console.log node)
> 
> >
> 
> >              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >              ;; however it has all gone pear shape here...
> 
> >              ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >              (js/console.log "(deref)NODE in on-click no longer has 'meta':"
> 
> >                              (clj->js (keys @node))))}
> 
> >           "Click me"])))))
> 
> >
> 
> > (defn tree
> 
> >   [{:keys [node] :as data} owner]
> 
> >   (reify
> 
> >     om/IDisplayName
> 
> >     (display-name [_] "Tree")
> 
> >     om/IInitState
> 
> >     (init-state [_]
> 
> >       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >       ;; decorate the value of the cursor from app-state
> 
> >       ;;  but store locally
> 
> >       ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> 
> >       {:node (assoc node :meta {})})
> 
> >     om/IRenderState
> 
> >     (render-state [_ {:keys [node]}]
> 
> >       (om/build
> 
> >        the-component
> 
> >        nil
> 
> >        {:init-state {:node node}}))))
> 
> > [/code]
> 
> >
> 
> > (any and all comments welcome!)
> 
> >
> 
> > Thanks.
> 
> 
> 
> --
> 
> Note that posts from new members are moderated - please be patient with your 
> first post.
> 
> ---
> 
> You received this message because you are subscribed to a topic in the Google 
> Groups "ClojureScript" group.
> 
> To unsubscribe from this topic, visit 
> https://groups.google.com/d/topic/clojurescript/SRqs211zf6E/unsubscribe.
> 
> To unsubscribe from this group and all its topics, 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.

Reply via email to