top | item 13410703

(no title)

snippy | 9 years ago

Thank you for your great explanation. I've read the documentation of re-frame, but I still can't figure out how it deals with reusable components and hierarchies.

Let's say I want to write a reusable datepicker component which sends an event like [:date [2017 1 16]] when the user clicks on that date. How can it send it to the calling component? The re-frame pub/sub message bus seems to be global, but what if I want to have several instances of the same component on the page?

The only solution I can come up with is to parameterize the component on instantiation, so that if I have a "person" component that uses the datepicker to set the day of birth of the person, the date-picker would be parameterized so that it would emit a global event such as [:set-person-day-of-birth <person-id> [2017 1 16]]. Is this how re-frame approaches hierarchies?

discuss

order

phrygian|9 years ago

I would say you don't. I think about it this way: use re-frame to write applications, but components must be self contained and have no knowledge of reframe. To do what you asked, I'll pass a function to the component. The function can then make the context-aware reframe call. That way all your component needs to do is to call the passed in function.

dkersten|9 years ago

It depends on what you mean by component. Reagent components (ie UI widgets), I agree. Components should be self-contained and as re-frame agnostic as possible. So instead of subscribing to the data they want, they could take in a ratom as an argument (because the subscribe function returns one anyway).

But if the component is larger (that is, not just the view, but also the handlers and subscriptions -- I'd probably call it something else, a service maybe...) then its a bit less simple because not just the view, but also the handlers and subscriptions need to be aware of the "instance" they are running. There's no well defined re-frame solution for this yet.

My favourite solution right now is to have each instance have its own ID as explained here: https://github.com/Day8/re-frame/issues/264#issuecomment-260...

That is, by convention, subscriptions are always [query-name instance-id <other optional data>] and messages are always [message-type instance-id <other optional data>] by convention. This way works quite well, but has the downside that it is by convention and there's no guarantee that other code will do it the same way.