Fork me on GitHub
#re-frame
<
2021-04-24
>
Charlot23:04:59

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"}) ?

p-himik09:04:05

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

emccue17:04:41

(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])]]})

emccue17:04:42

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

emccue17:04:40

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

emccue17:04:10

like lets say you wrote that effect manager above, it generates a random number between 0 and 1, just the fundamental randomness

emccue17:04:55

(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]])

emccue17:04:27

first I would move the effect to a namespace and expose a function that returns something you can put in :fx to do it

emccue17:04:36

so you would use it like this

emccue17:04:39

(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]))})

emccue17:04:53

and then build functions on top of that to do more complicated things

emccue17:04:58

(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))))))

emccue17:04:23

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

emccue17:04:42

but fundamentally you should be able to get by with very few reg-fx declarations

emccue17:04:07

(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]))})

Charlot18:04:48

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.