Fork me on GitHub
#re-frame
<
2024-06-09
>
rende1111:06:01

Hi, is there any way to shorten such a record or make it more linear? I would like it to be clear which chain of events is called without viewing all the events one by one.

(rf/reg-event-fx
   :evt/run
   (fn [_ _]
     {:fx [[:dispatch [:evt/one]]]}))

  (rf/reg-event-fx
   :evt/one
   (fn [_ _]
     (let [res (+ 2 2)]
       {:fx [[:dispatch [:evt/two res]]]})))

  (rf/reg-event-fx
   :evt/two
   (fn [_ [_ value]]
     (let [res (+ value 10)]
       {:fx [[:dispatch [:evt/three res]]]})))

  (rf/reg-event-fx
   :evt/three
   (fn [_ [_ value]]
     {:fx [[:dispatch [:success value]]]}))

p-himik12:06:27

The best approach relies on a bit of discipline where all "util-level", just reusable events, or maybe even all events are implemented with reg-event-fx that you use on a function defined separately. In addition, the :dispatch effect and its cousins are not used at all and instead the separately defined handlers are used. You may or may not have a wrapper to avoid having to pass a vector of arguments instead of the arguments themselves. Your code can be then rewritten as:

(defn success [cofx value]
  ...)

(defn three [cofx value]
  (success cofx value))

(defn two [cofx value]
  (let [res (+ value 10)]
    (three cofx res)))

(defn one [cofx]
  (let [res (+ 2 2)]
    (two cofx res)))

(defn run [cofx]
  (one cofx))

(rf/reg-event-fx :evt/run (fn [cofx _] (run cofx)))
(rf/reg-event-fx :evt/one (fn [cofx _] (one cofx)))
(rf/reg-event-fx :evt/two (fn [cofx [_ value]] (two cofx value)))
(rf/reg-event-fx :evt/three (fn [cofx [_ value]] (three cofx value)))
(rf/reg-event-fx :success (fn [cofx [_ value]] (success cofx value)))
It then becomes a plain chain of functions. And if some event is not used as an event, you don't need to register it at all - it's just a plain function.

think_beret 1
rende1115:06:27

@U2FRKM4TW Sorry, It's not clear for me - how I can avoid of using :dispatch?

p-himik15:06:20

My code above doesn't use :dispatch.

p-himik15:06:52

You will have to use dispatch to initiate events as a consequence of a user/browser action. But it's not :dispatch.

rende1115:06:01

Oh, I think I figured, it would work when we want to pass some kind of value through a chain of events.

p-himik16:06:45

It would work in any case because it ends up being just calling regular functions. The only potential issues if some event handlers require injecting extra co-effects. That can probably be handled in some clever way but such a situation is quite rare in my experience to be bothered enough to think about it.

rende1116:06:29

Another example - Here is 3 operations which one should be executed sequentially, but some on then(2) consists of chains of events. I wan't to achive this order of events: :generate-password :store-password :generate-account-data :store-account-data :create-account Some of them use the results of previous operations I have only one opportunity to put them one into another?

(rf/reg-event-fx
   :evt/run-workflow
   (fn []
     {:fx [[:dispatch [:generate-password {:on-success [:dispatch [:store-password]]}]]
           [:dispatch [:generate-account-data {:on-success [:dispatch [:store-account-data]]}]]
           [:dispatch [:create-account]]]}))

p-himik16:06:32

Same exact principle - extract the handlers into their own functions and call those functions directly. Use reg-event-* functions mainly for user- or browser-triggered events.

rende1119:06:22

But these events produces different effects, and in this case they are should be merged somehow?

p-himik20:06:32

An fx event handler accepts coeffects and returns effects. If you always pass :db around and don't rely on other coeffects, the effects map can play the role of the coeffects map. So you can chain any fx handler functions together. There's a relevant discussion logged here: https://gist.github.com/bowbahdoe/7fd8714cd910d43eb3229f967d95cbc6 And a write-up here: https://gist.github.com/olivergeorge/edc572eab653cc228ec5ecbbcc8271a2

fabrao17:07:43

@U4U68ADKR why don't you use https://github.com/day8/re-frame-async-flow-fx ? You can control every steps.

p-himik17:07:34

There's been plenty of discussions of downsides of using that library here, especially when done for anything other than app startup.