This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
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]]]}))
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.@U2FRKM4TW
Sorry, It's not clear for me - how I can avoid of using :dispatch
?
You will have to use dispatch
to initiate events as a consequence of a user/browser action. But it's not :dispatch
.
Oh, I think I figured, it would work when we want to pass some kind of value through a chain of events.
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.
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]]]}))
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.
But these events produces different effects, and in this case they are should be merged somehow?
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
@U4U68ADKR why don't you use https://github.com/day8/re-frame-async-flow-fx ? You can control every steps.