That's what I had in mind. If your current implementation is similar to what's 
suggested in many react examples, it may not be as bad as I thought. It still 
feels a little nasty to me though.

Daniel's point about your om version is good too. I had forgotten about the 
past issues with multimethods.

> On 4 Dec 2014, at 21:04, Colin Yates <[email protected]> wrote:
> 
>> On Thursday, 4 December 2014 12:53:27 UTC, Lucas Bradstreet  wrote:
>> If I understand this correctly, you're actually passing in a om/build'ed 
>> component as a part of a cursor to another component? I'm not sure whether 
>> this is the cause but I think this is very likely bad form.
> Yes, that is starting to become my intuition as well.
> 
> What would be the analog though of the multitude of React examples where they 
> compose their components? AIUI those components will be passed through as 
> props.children, hence I started out this way here.
> 
> A workaround as you say is you pass just the dependant's required cursor and 
> the dependant builder's var via opts, something like:
> 
> [code]
> (defn build-child [cursor owner]...)
> (defn wrap-it-up [...]
> (om/build some-common-wrapper childs-cursor {:opts {:child-builder 
> build-child}})
> [/code]
> 
> Is that what you meant?
> 
> (I won't comment on the stylistic qualities of my code, it was under a 
> comment further up as ";; TODO - prototype" which if I recall correctly is a 
> license to hack away and then revist "when there is time" :)!)
> 
>> 
>> If you want to do something like that I would suggest you passed in the 
>> cursor for the subcomponent that you wish to build, and a fn to build the 
>> component as an opt. Note, you shouldn't pass in anything via opts that 
>> should cause a rerender when changed, so this would preclude creating a 
>> closure over data (your cursor) and passing it via the opts. I would 
>> probably move all of the cursor building out of :fn and make it happen in 
>> the multimethod, passing the result to filter-header, along with bound-tree 
>> fn as an opt.
>> 
>> Then filter-header will call build on bound-tree with the data you passed 
>> in. 
>> 
>> That's all assuming you can't refactor it to avoid this. I've generally only 
>> used this pattern if I want to wrap components with a generic component 
>> (e.g. a drag drop component). 
>> 
>> Lucas
>> 
>> 
>> 
>>> On 4 Dec 2014, at 20:29, Colin Yates <[email protected]> wrote:
>>> 
>>> I have isolated the code in question and it was written very early on (e.g. 
>>> woooh, here be dragons :)):
>>> 
>>> Essentially I have a component which calls a multimethod to render a child. 
>>> This is the implementation of that multimethod. This itself uses a common 
>>> component and passes in components to that common component.
>>> 
>>> Adding a key to the returned component (that isn't a keyword but a 
>>> string(!)) gives React enough help so it doesn't unmount it. 
>>> 
>>> For clarity, filter-header simply displays a nice formatted title and puts 
>>> "main-component" into the body.
>>> 
>>> [code]
>>> (defmethod layout/render-right-component ::consultant
>>> [{:keys [owner data]}]
>>> (om/build
>>>   c/filter-header
>>>   {:id :consultants
>>>    :main-component
>>>    (om/build
>>>      tree/bound-tree
>>>      nil
>>>      {:fn (fn [_] {:nodes (om/observe owner (state/all-consultants))
>>>                    :selected-ids (-> data :filter :consultants 
>>> :selected-ids)
>>>                    :expanded-ids (-> data :filter :consultants 
>>> :expanded-ids)
>>>                    :local-search (-> data :filter :consultants 
>>> :local-search)})
>>>       :opts      {:change-fn
>>>                   #(search data true)
>>>                   }})
>>>    }
>>>   ;; WITH THIS REACT NO LONGER UNMOUNTS
>>>   {:react-key "Consultants"})
>>> )
>>> [/code]
>>> 
>>> As to the reduced problem, I need to keep poking, and I still don't 
>>> understand why it needs the "Consultants" key...
>>> 
>>> This realising components in state (e.g. the :main-component) isn't doing 
>>> it for me so I think I might utilise more multi-methods. The problem is 
>>> always how to deliver the focused cursor into the defmethod (e.g. 
>>> render-right-component really wants to take in the cursor at (:filter 
>>> :consultants). But that is another experiment.
>>> 
>>> Any advice is welcome.
>>> 
>>> On Thursday, 4 December 2014 12:13:16 UTC, Lucas Bradstreet  wrote:
>>>>> On 4 Dec 2014, at 20:02, Colin Yates <[email protected]> wrote:
>>>>> 
>>>>> Hi Lucas, thanks for the info.
>>>>> 
>>>>> You are right - I should have been clearer. My scenario is that the 
>>>>> component hierarchy itself isn't changing only the app-state that the 
>>>>> hierarchy is mapped to.
>>>>> 
>>>>> In its simplest form, think of a combo-box. The app-state is {:text "" 
>>>>> :results []}. The component has an input field mapped to :text and a <ol> 
>>>>> mapped to :results. Changing :text populates :results accordingly.
>>>>> 
>>>>> Your point about keys is worth investigating. Where I am setting keys 
>>>>> (mainly on dynamic children) they aren't changing. I'm not setting them 
>>>>> elsewhere though, which might be worth a look.
>>>> 
>>>> Hmm. Maybe the lack of keys on some components may be the issue. Perhaps 
>>>> react can't assume that the components are the same and thus unmounts and 
>>>> remounts them (the dom diffing ensures this is still fast) e.g imagine an 
>>>> unordered list where a list item is inserted mid list. I haven't tested 
>>>> whether this is true. 
>>>> 
>>>>> 
>>>>> Another clarity question - if an ancestor component is remounted does 
>>>>> that cause all children to be remounted? It might be something much 
>>>>> higher up in the hierarchy causing a remount...
>>>> 
>>>> I would think so. Again, I haven't tested this. 
>>>> 
>>>>> Thanks for confirming my assumptions anyway, I will dig in a bit deeper.
>>>> 
>>>> Please let us know the result. 
>>>> 
>>>> Cheers
>>>>> 
>>>>>> On Thursday, 4 December 2014 11:39:44 UTC, Lucas Bradstreet  wrote:
>>>>>> Hi,
>>>>>> 
>>>>>> Changes to app state *can* cause components to be unmounted. Imagine a 
>>>>>> component that renders another component, if a boolean value in the app 
>>>>>> state is true, otherwise it renders and empty div. When the boolean 
>>>>>> changes from true to false and the component is re-rendered, the 
>>>>>> subcomponent will be unmounted. 
>>>>>> 
>>>>>> However, if the subcomponent should be re-rendered in both cases, it 
>>>>>> should not be unmounted. 
>>>>>> 
>>>>>> Thinking about it, you're probably mistakenly using a different 
>>>>>> react-key between the renders. This will cause a new component to be 
>>>>>> mounted as it is not treated as a continuation of the previous 
>>>>>> component. 
>>>>>> 
>>>>>> Lucas
>>>>>> 
>>>>>> 
>>>>>>> On 4 Dec 2014, at 19:29, Colin Yates <[email protected]> wrote:
>>>>>>> 
>>>>>>> Hi all,
>>>>>>> 
>>>>>>> I am seeing a component consistently unmount/remount every time the 
>>>>>>> application state changes. If I change the local state instead then it 
>>>>>>> doesn't umount but simply re-renders as I expected.
>>>>>>> 
>>>>>>> I didn't expect changes in app-state to cause an unmount/remount only a 
>>>>>>> re-render (as that is my understanding of React's lifecycle). Further, 
>>>>>>> since I am talking about this my assumption (and the behaviour I am 
>>>>>>> seeing) is that om will only call the render protocol method if the 
>>>>>>> values have actually changed.
>>>>>>> 
>>>>>>> If my assumptions are correct I will see if I can reduce the problem 
>>>>>>> into a simple gist.
>>>>>>> 
>>>>>>> The reason this is a pain, performance aside, is because a re-mount 
>>>>>>> loses focus and this specific component is a text field. I notice in 
>>>>>>> the discussion on text-fields in the Basic tutorial "text" is component 
>>>>>>> local, maybe now I understand why as this seemed to me to go against 
>>>>>>> the grain of what is advised to go into local state...
>>>>>>> 
>>>>>>> Can somebody please clarify?
>>>>>>> 
>>>>>>> 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 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.
> 
> -- 
> 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.

Reply via email to