I've just been racking my brains for the last couple of days on a similar 
problem, and this amazingly solved it. So firstly thank you very much!

If I've read your description of reagent-phonecat tutorial 
<https://github.com/vvvvalvalval/reagent-phonecat> correctly, my scenario 
is very similar in that I have one Form-2 component which can potentially 
edit any number of data items with the same structure. If through the UI I 
select a different item to edit, I want to whole component to reflect the 
new data item. In my own case, the component was re-rendering to display 
the data of the newly selected item, but any attempts to change that data 
resulted in attempts to change the data on the previous item. I eventually 
discovered that the reason for this is due to a custom input component 
which registers event handlers in the initialization of the Form-2 
component, and these handlers were set only once to update the first data 
item selected.

This "trick" works in that it produces the result I was after, namely that 
the whole Form 2 component is now re-initialized whenever I change my data 
item via the UI.

I have two questions:

1. Just as with your component, I am passing a unique ID (e.g. dynamic-id) 
as the first argument in the component. Can anyone explain why this alone 
is not sufficient to trigger a re-initialization of my Form-2 component, 
and why adding ^{:key dynamic-id} meta-data does cause a full 
re-initialization? I have read both Creating Reagent Components 
<https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components> and When 
do components update? 
<https://github.com/Day8/re-frame/wiki/When-do-components-update%3F> and 
understand those aspects of Reagent, however I don't really know how 
exactly this :key metadata fits into the picture.

2. As has already been asked, do we know if this technique can be relied 
upon ongoing?

Thank you, Ali

On Monday, May 25, 2015 at 8:18:59 PM UTC+5:30, Val Waeselynck wrote:
>
> I just did some more experimenting, and it seems you don't even need a 
> list at all, adding metadata to the vector is enough :)
>
> (defn parent-component []
>   [:div
>    ;; ...
>    ^{:key dynamic-id} [my-stateful-component dynamic-id arg1 arg2 etc.] ;; 
> if dynamic-id changes, my-stateful-component will be 'reinitialized'.
>    ;; ...
>    ])
>
> That's a big improvement actually, because lists cannot be returned from a 
> Reagent render function (they have to be in another element).
>
>
>
> Le lundi 25 mai 2015 16:00:47 UTC+2, Mike Thompson a écrit :
>>
>>
>> As a collection point for these sorts of tips, I've created a Wiki page 
>> on the re-frame repo:
>> https://github.com/Day8/re-frame/wiki/More-advanced-Reagent-techniques
>>
>>
>> On Monday, May 25, 2015 at 11:48:56 PM UTC+10, Mike Thompson wrote:
>>>
>>>
>>> Nice!
>>>
>>> There's a small, related trick which can *sometimes* makes thinks 
>>> neater: 
>>>
>>>        (list [my-stateful-component {:key dynamic-id}  arg1 arg2 etc.])
>>>
>>> When looking for an "key",  if Reagent doesn't find metadata, it will 
>>> look at the first parameter, and, if it is a map, then it will look to see 
>>> if it contains a ":key".  If so, it will use that. 
>>>
>>> Code:
>>>
>>> https://github.com/reagent-project/reagent/blob/a2b5acb68f2afb88b0da4e9a7d7acac1d8eceb5d/src/reagent/impl/template.cljs#L184-L187
>>>
>>>
>>>
>>>
>>>
>>> On Monday, May 25, 2015 at 10:59:01 PM UTC+10, Val Waeselynck wrote:
>>>>
>>>> Just a little trick I found and would like to share - maybe you all 
>>>> already know this, or you have a better solution for this problem - sorry 
>>>> if that's the case!
>>>>
>>>> *THE IDEA*
>>>>
>>>> In some cases, you can easily manage the lifecycle of a stateful 
>>>> component by putting it in a list (as the single item), with an 
>>>> appropriate 
>>>> :key.
>>>> (By stateful component, I mean typically the kind you define with a 
>>>> function returning a function that closes over some local atom or cursor).
>>>> This way 
>>>>
>>>> Here's some sample code, that you can also see in this Gist 
>>>> <https://gist.github.com/vvvvalvalval/937f69ef04872b649e82>:
>>>>  
>>>> (defn parent-component []
>>>>   [:div
>>>>    ;; ...
>>>>    (list ^{:key dynamic-id} [my-stateful-component dynamic-id arg1 arg2 
>>>> etc.]) ;; if dynamic-id changes, my-stateful-component will be 
>>>> 'reinitialized'.
>>>>    ;; ...
>>>>    ])
>>>>
>>>> The idea is that the lifecycle of my-stateful-component is 'bound' to 
>>>> dynamic-id, in the sense that whenever parent-component renders with a 
>>>> new dynamic-id, my-stateful-component is mounted again.
>>>>
>>>>
>>>> *EXAMPLE*
>>>>
>>>> There's a subtle bug in the current implementation of the reagent-phonecat 
>>>> tutorial <https://github.com/vvvvalvalval/reagent-phonecat> (which I 
>>>> wrote, guilty as charged!).
>>>> (For those who don't know it, it's an online catalog of Android phones, 
>>>> with a page that displays the list of phones, and a more detailed page for 
>>>> each phone).
>>>> If you navigate to the page of a phone, then manually change the URL to 
>>>> the page of another phone, it the page won't update accordingly, because 
>>>> it 
>>>> is stateful and is still using the old state - that of the previous phone.
>>>>
>>>> I've now fixed it with the above strategy - the phone page component is 
>>>> :key-ed with the id of the phone, so that its initialization code is 
>>>> re-run 
>>>> when the phone changes  - see diff 
>>>> <https://github.com/vvvvalvalval/reagent-phonecat/commit/bfafe178d8a6ba14756e4083fe23f0204f448489>
>>>> .
>>>>
>>>>
>>>> Any thoughts?
>>>>
>>>

-- 
You received this message because you are subscribed to the Google Groups 
"Reagent-Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to reagent-project+unsubscr...@googlegroups.com.
To post to this group, send email to reagent-project@googlegroups.com.
Visit this group at https://groups.google.com/group/reagent-project.
For more options, visit https://groups.google.com/d/optout.

Reply via email to