Fork me on GitHub
#re-frame
<
2024-02-20
>
Stefano09:02:06

Hello everyone! I have a question on what would be the best approach to handle this situation in re-frame. Let's say I have this:

(rf/reg-event-fx 
 :event-0
 {:dispatch-n [[:event-1] 
               [:event-2]]})
And that :event-1 further dispatches other events via :dispatch-n, for example:
(rf/reg-event-fx 
 :event-1
 {:dispatch-n [[:event-1-0] 
               [:event-1-1] 
               [:event-1-2]]})
Is there any way to dispatch :event-2 after all or some of the other events have been handled? The options I explored so far are: 1. Dispatch another event in the :event-1 handler (or its "children") only to notify that the event has been handled. 2. Use rf/add-post-event-callback (maybe wrapped in a reg-fx) to dispatch :event-2 after one or more of the events have been handled. 3. Poll the db until some condition is met. All of these have trade offs and I am wondering if there are other better options. I would really appreciate any suggestion. Thanks!

p-himik09:02:28

The most robust and simple solution would be to avoid "util" events and instead compose functions that receive and return fx.

Stefano09:02:08

Umh, seems interesting. Are you able to provide an example? Let's say :event-1 doesn't know about :event-2 . How that would look like?

wevrem15:02:31

Note that :dispatch-n is deprecated. If :event-1 doesn’t know about something, but needs to dispatch it, then it needs to be provided with it, for example, as an argument.

(rf/reg-event-fx
 :event-0
 (fn [{:keys [_db]} _]
   (let [event-for-after [:event-2 arg1 arg2]]
     {:fx [[:dispatch [:event-1 event-for-after]]]})))

(rf/reg-event-fx
 :event-1
 (fn [{:keys [_db]} [_ event-for-after]]
   {:fx [[:dispatch [:event-1-0]]
         [:dispatch [:event-1-1]]
         [:dispatch [:event-1-2]]
         [:dispatch event-for-after]]}))
Or you could stash :event-2 in app/db.
(rf/reg-event-fx
 :event-0
 (fn [{:keys [db]} _]
   {:db (assoc db :event-for-after [:event-2 arg1 arg2])
    :fx [[:dispatch [:event-1]]]}))

(rf/reg-event-fx
 :event-1
 (fn [{:keys [db]} _]
   (let [{:keys [event-for-after]} db]
     {:db (dissoc db :event-for-after)
      :fx [[:dispatch [:event-1-0]]
           [:dispatch [:event-1-1]]
           [:dispatch [:event-1-2]]
           [:dispatch event-for-after]]})))

p-himik19:02:20

When one event doesn't know about the other but needs to dispatch it and also rely on a particular problem makes it sound like you're trying to make the problem harder than it needs to be. :) For each involved event, use only reg-event-fx and extract the handler as a separate defn. Instead of dispatching events from event handlers, call their handlers directly. Also, FWIW when you do need to dispatch multiple events from an event handler, I definitely prefer dispatch-n over fx+dispatch. I couldn't care less that it's deprecated. :) If such an effect wouldn't have been built into re-frame, I'd create it myself. Fx is still useful of course, but not as frequently.