This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-03
Channels
- # announcements (4)
- # aws (19)
- # babashka (55)
- # beginners (40)
- # biff (4)
- # calva (9)
- # cherry (3)
- # cider (8)
- # clj-kondo (26)
- # clj-yaml (3)
- # clojure (92)
- # clojure-austin (14)
- # clojure-europe (21)
- # clojure-nl (1)
- # clojure-norway (5)
- # clojure-portugal (3)
- # clojure-uk (2)
- # clojurescript (48)
- # conjure (19)
- # datalevin (14)
- # docker (13)
- # emacs (3)
- # fulcro (21)
- # gratitude (14)
- # improve-getting-started (1)
- # introduce-yourself (2)
- # joker (4)
- # juxt (2)
- # lsp (12)
- # malli (5)
- # meander (17)
- # off-topic (13)
- # re-frame (7)
- # scittle (2)
- # test-check (2)
I have an event handler with a cofx that creates an object, and I want to store a reference to this object in the app-db. It's not obvious to me how to achieve this. Should I dispatch in the reg-fx
function?
If the event is registered with reg-event-db
, you just return the new app-db value, so all you need to do is add that object to it and return it.
If you used reg-event-fx
, then you need to return a :db
effect with that new app-db value.
Thanks! Maybe I am doing this wrongly... I'm doing something like so:
(rf/reg-fx
:foo/create-a-thing!
(fn [thing-data]
(js/fw.Thing. thing-data)))
(rf/reg-event-fx
:foo/thing
(fn [{db :db} [_ thing-data]]
(let [new-db (assoc-in db [:foo :thing] thing-data)
already-created? (get-in db [:foo :thing-created?])]
(merge {:db new-db}
(when (and (not already-created?) thing-data)
{:db (assoc-in new-db [:foo :thing-created?] true)
:foo/create-a-thing! thing-data})))))
Instead of already-created?
I would like to store the object.Hold on. In the OP you say: "a cofx that creates an object".
"Cofx" stands for "coeffect", and coeffects in re-frame are things registered with reg-cofx
and that make their way into the context right before event handler that use those coeffects are called. Usually, you use them via the inject-cofx
built-in interceptor.
But in your code above, you're creating an effect. Usually effects are used for side-effects, it's a way for re-frame to make event handlers talk to the outside world, in a way. The :db
effect changes the app-db, the :dispatch
effect dispatches a new event, and so on.
So in your case, if (js/fw.Think. ...)
does not side-effect, I'd just construct it right in that event handler and put it in the :db
right there, without any [co]effects.
If it doesn't side-effect but you still want to keep it separate for some reason, then put it in a coeffect.
And if it does side-effect, put it in its own effect, just the way you're doing it above, but restructure the effect in such a way so that it changes app-db. Not directly, of course, but via some event created specifically for the thing. That's needed because return values of effects are ignored - their sole purpose is side-effects.
Yeah, sorry, the terminology has never really landed right with me. I read this in the docs from reg-event-fx
and thought I was registering a cofx:
Example Usage:
#!clj
(reg-event-fx
:event-id
(fn [cofx event]
{:db (assoc (:db cofx) :some-key (get event 2))})) ;; return a map of effects
Anyway, instantiating fx.Thing
side-effects a lot, so maybe it makes sense to put it in an effect? If so my question actually is how I:
> restructure the effect in such a way so that it changes app-db. Not directly, of course, but via some event created specifically for the thing.
Should I dispatch that event from :foo/create-a-thing!
?Yep, exactly.
(rf/reg-fx ::create-thing
(fn [data]
(let [thing (js/Thing. data)]
(rf/dispatch [::-store-thing thing]))))
(rf/reg-event-db ::-store-thing
(fn [db [_ thing]]
(assoc db :the-thing thing)))
(rf/reg-event-fx ::do-stuff
(fn [{db :db} [_ data]]
{:db ...
::create-thing data}))