Fork me on GitHub
#re-frame
<
2017-01-23
>
piotr-yuxuan00:01:28

Hi there, I’ve been wondering where I could post question about how to design re-frame events flow. The following is a question about how to achieve some pattern in re-frame, not really an issue. If you know about any other discussion rooms where I could ask it, please just tell me 🙂 I'd like to chain effectful handlers. For example, let's say I want to retrieve n parent commits on GitHub git repository for Linux kernel: I'll issue a request to retrieve the last commit (with the standard http effectful handler). On success I dispatch another event which gets that commit retrieved + number n-1 of commits to be retrieved. Where should I put these data? Aren't they coeffect of the next event? Once I've got all the commits I should issue a final event which takes all these commits as coeffects, right? were should I put these data? My first attempt was to use interceptors to express we need to gather some coeffects before we update app-db. However, how can I trigger an effectful handler from interceptor? is it ill-designed? It's completely possible I'm wrong and I miss something very trivial about re-frame design.

piotr-yuxuan17:01:22

mikethompson: Thanks for your reply. Yeah I’ve given a look on this project but I feel (for my usecase) I could natively achieve the same thing with re-frame.core/add-post-event-callback and pass data from event to event in event vector. However I feel it may be a better abstraction to use coeffects, augment them by transitory event "get the parent of the last commit in the coeffects" untill coeffects are complete enough (= contains n commits) for the main event “put n last commits in app-db” to occur. However I don’t know how to properly dispatch an event with coeffects. Any thought?

witek12:01:14

Another conceptual question. Is it a good practice to put functions into subscription results? Example: I want to create a generic 'button' component. The reagent-component-function takes a subscription-vector as parameter, subscribes to it and gets text, tooltip and on-click from the dereferenced subscription. Is that good practice?

sandbags12:01:29

I'm not sure if the answer is the same as to the previous question but my situation is perhaps a little simpler: After initialising the first view (with a logo & throbber) my app should bootstrap some data from the server. The simplest approach that occurs to me is to change (reg-event-db :initialize-db ...) to (reg-event-fx :initialize-db ... :dispatch [:bootstrap]). Does that seem resaonble?

mikethompson12:01:44

@witek I see no problem, if you need that kind of flexibility. The subscription delivers new tooltip and label over time? If not, seems slightly overkill, but no great problem.

mikethompson12:01:40

@sandbags seems very reasonable. Where it get more complicated is when there's two calls to the server, and we have to wait for both, and one or the other could fail, etc. That's when re-frame-async-flow comes into its own.

witek12:01:38

@mikethompson Thats exactly my problem. Label and tooltip do not change over time. But I have multiple buttons on my page. They all would have different subscription vectors and therefor different labels and tooltips. That way I would move the definition of labels and tooltips out of my view into subscriptions (which is my domain logic). This would allow simpler internationalization, I have hoped. But my application would have a lot of subscription-instances. For all buttons, all fields, etc...

witek12:01:16

Not sure if this is a good idea.

iGEL15:01:48

Hey! A stupid newbee question, but where should I dispatch the event to fetch data via ajax I need for the default panel? Doing so in the view feels wrong, but since it's so far the only place where I determinate the active panel, I also don't have a good idea where else to do it...

akiroz15:01:28

@igel if you have multiple panels, you can have an initialize event for each panel and fetch your data there.

iGEL15:01:25

Ok, makes sense. Thanks

witek16:01:02

Is there a way to check if a value is a subscription (which needs to be dereferenced) or if it is already the dereferenced value? I want to create a component which as parameter accepts a map of data or a subscription which provides the map of data.

dragoncube20:01:49

@mikethompson are there any draft of doc rewrite for “Dynamic Subscriptions” for 0.8.0+ ?

geoffs20:01:20

@witek I would say you should make that component just always take the map as data. Then it can come from whatever source you want, including a subscription.

geoffs20:01:12

if there's one common subscription that you use it with often, then you could make a wrapper component that simply derefs the subscription and passes it as a map into the "real" component

witek21:01:46

@geoffs But then the parent component would have to dereference the subscription. And when this parent component uses multiple child chomponents with different subscriptions, that whole thing would have to be rerendered, whenever one oft the subscriptions change, right?

geoffs21:01:48

hmmm, I don't know enough about re-frame/reagent to really answer that question. But even if that is true, and that actually creates a performance problem (which I'd be skeptical about assuming it does, always measure!), you can still solve it the same way. introduce another component in between parent and data-using-child

geoffs21:01:06

where all it does is deref the subscription and pass it into data-using-child

geoffs21:01:41

and at that point I would put the subscription itself into the deref component. Why even have the component in the parent if it's not being used?

geoffs21:01:53

other than to pass it in to the appropriate child

geoffs21:01:32

has some links for further reading

geoffs21:01:01

I know my description is kind of abstract, but I'm basically just describing the "Container/Component" pattern

witek21:01:08

Thats becouse I am thinking of generic reusable components. Like a button for example. It could get a map with label, tooltip, etc. Or a subscription, when I want domain logic to provide the data.

geoffs21:01:56

ah, interesting. that clarifies things. But I would still do it with two components 🙂 I personally have a strong dislike for passing in really different things for the same argument and then putting in logic to switch on the type. I would rather have e.g. [button {:map-of-args}] and [button-sub subscription-of-args) and have button-sub be a thin wrapper that passes the subscription data along to button

geoffs21:01:35

if that makes sense and is actually speaking more to what you're trying to accomplish

sandbags21:01:53

@mikethompson also kudos to you guys for making re-frame & re-com available under the MIT license

qqq21:01:21

re-com especially, the GUI elements are beautiful

sandbags21:01:47

Porting a compojure+reagent+bootstrap app to liberator+re-frame+re-com and i'm really liking how its turning out

sandbags21:01:12

it's a small app but where i felt v1 was already getting a bit of a mess, this feels like it could scale out & up nicely

sandbags22:01:03

Not sure if there is a good way of fixing this but the re-com progress-bar component the display of the % isn't very good at low values

sandbags22:01:15

since it displays the text as white-on-light-grey