Hello, starting out in re-frame and liking it. I'm trying to move beyond the simplest stuff, and am trying to figure out how to write my first interceptor/coeffect.
I'm writing a little dice-rolling app, and I want to abstract out the randomness into an effect.
Assuming for a moment I have a working reg-cofx
'ed add-roll-info
, I am trying to now setup the reg-event-fx
call.
But how would I access which roll I'm wanting to get random numbers for in the (inject-cofx :add-roll-info {:the "map or roll-id to look up to produce the map"})
?
I'm not sure what you're asking exactly, but have you seen this documentation section and the ones below it? http://day8.github.io/re-frame/Coeffects/#meet-reg-cofx
(rf/reg-fx
::generate-random-number
[when-done]
(rf/dispatch-sync
(when-done (Math/random))))
(rf/reg-event-fx
::got-random-number
[{:keys [db]} [_ x]
{:db (assoc db :x x)}) ;; pick something better than :x, hopefully something scoped
(rf/reg-event-fx
::clicked-dice-roll-button
[{:keys [db]} _]
{:fx [[::generate-random-number (fn [x] [::got-random-number x])]]})
at least to me reg-cofx makes sense for getting the current time - if you were to add a :tick event to your model that would become cumbersome and it is a benefit of being in an impure language that you can make a practical decision like that
but anything else I either try to build out from effect managers I already wrote or in really rare cases add make a new effect manager
like lets say you wrote that effect manager above, it generates a random number between 0 and 1, just the fundamental randomness
(ns your.project.effects.random)
(rf/reg-fx
::generate-random-number
[when-done]
(rf/dispatch-sync
(when-done (Math/random))))
(defn generate-random-number [when-done]
[[::generate-random-number when-done]])
first I would move the effect to a namespace and expose a function that returns something you can put in :fx to do it
so you would use it like this
(ns ...
(:require [your.project.effects.random :as random-fx]))
(rf/reg-event-fx
::clicked-dice-roll-button
[{:keys [db]} _]
{:fx (random-fx/generate-random-number (fn [x] [::got-random-number x]))})
and then build functions on top of that to do more complicated things
(ns your.project.effects.random)
(rf/reg-fx
::generate-random-number
[when-done]
(rf/dispatch-sync
(when-done (Math/random))))
(defn generate-random-number [when-done]
[[::generate-random-number when-done]])
(defn in-range [start-inclusive stop-exclusive when-done]
(generate-random-number
(fn [x]
(let [choices (range start-inclusive stop-exclusive)
which-one (Math/floor (* x (- stop-exclusive start-inclusive)))]
(when-done (nth choices which-one))))))
a non-trivial amount of re-inventing the wheel sure - feel free to make more randomness fx if its convenient to just call normal side effecting fns
but fundamentally you should be able to get by with very few reg-fx declarations
(ns ...
(:require [your.project.effects.random :as random-fx]))
(rf/reg-event-fx
::clicked-dice-roll-button
[{:keys [db]} _ {:keys [roll-id]}]
{:fx (random-fx/in-range 1 7 (fn [x] [::got-random-number roll-id x]))})
That's a very thorough explanation, and I'm gonna have to parse it at length. http://day8.github.io/re-frame/Interceptors/ I think gave the prompt I needed for my current issue, which was thinking that I need to get the even from the event-hander fn definition, into the the injected-cofx part of the declaration, when instead i should fetch the information I need out of the event in the context map.