Fork me on GitHub
#reagent
<
2018-03-04
>
roti10:03:10

How does reagent deal with reusable components? The issue I have is that ratoms are basically in the functional closure of the render function, and by default all usages of that component share those atoms. Those atoms effectively represent the local state of the component, so I need an additional step to "instantiate" my component where it's used (to have the local component state effect)

roti10:03:32

E.g. you have a dropdown component, and what to keep some things in the local state, like whether the dropdown is open or not, you need to make something like this.

(defn make-dropdown[]
    (let [local-state (r/atom nil)]
       (fn [....]
            ;;render function here
       )))

;;make an instance of the dropdown
(def customers-dropdown (make-dropdown))

;;and now use it
(defn mycomponent[]
....
[customers-dropdown ....]
....
)

roti10:03:12

are there other ways to do this? or at least with a more elegant api?

gadfly36110:03:24

You don't need to 'instantiate' the component. You can just call it directly inside of mycomponent as [make-dropdown] (skipping the def customers-dropdown altogether)

roti10:03:33

i don't think that will work. that way every rendering of mycomponent will have a new localstate for dropdown

gadfly36110:03:23

The reason you have that nested fn is to avoid that

gadfly36110:03:33

So it will only get created the one time

roti10:03:06

hmm, that looks suspiciously easy. how does reagent know when to create a new component instance, and when to use an already existing one?

roti10:03:45

i mean I could use my dropdown in 3 other components. and I want to have 3 instances, with 3 local states

roti10:03:36

but I have to say, pretty clever

gadfly36110:03:56

You could even use make-dropdown three times inside of one component, like mycomponent and each would have it's own local ratom that gets closed over

roti10:03:24

so you mean it's actually the expected behaviour

gadfly36110:03:50

Yeah, it is a form-2 component (docs linked above)

roti10:03:54

thanks, but I still wonder how reagent can distinguish between creating a component and using it

justinlee16:03:23

@roti when reagent first creates a component, it calls the render function once. it inspects the return value from the render function. if the return value is a vector, then it is a form-1 component, and that original function becomes the render function. if the return value is a function, then the new returned function becomes the render function, and it is a form-2 component.

justinlee16:03:12

I might put this behavior in the Too Clever By Half folder, except that it allows you to use reagent using normal function and no macros, which is pretty impressive