re-frame

https://github.com/Day8/re-frame/blob/master/docs/README.md https://github.com/Day8/re-frame/blob/master/docs/External-Resources.md
Richie 2021-05-16T14:53:09.477Z

In order to think of my current app state as the result of a fold over the events I’d have to distinguish events from “outside” (like outside input. button click dispatches event) vs events as effects from other events. If I dispatch event :b in the handler for event :a then I wouldn’t want to persist/replay event :b. Either that or my replay/reduce logic doesn’t process events that result from other events.

Richie 2021-05-16T14:57:43.477900Z

Sorry, I haven’t formed a question yet. I’m thinking this through and looking for guidance.

Richie 2021-05-16T15:02:48.479500Z

I guess I would want to persist all events as they’re handled. When I replay the events I would ignore any effects that the handlers return. That gets me the same app state. Ok, that seems clear.

Richie 2021-05-16T15:24:53.482600Z

I’m not sure how to implement this. My first thought was to prepend a global interceptor with an :after that erases any :fx. My second thought is to use this add-post-event-callback function that I just found. I could add a function that clears the event queue of all events to be processed and then enqueue the single next event that I want it to process. I’d get this event from my persistence.

emccue 2021-05-16T15:37:14.485600Z

@rgkirch In your event handlers you can always just do this

emccue 2021-05-16T15:39:58.488700Z

(defn save-history [handler-fn]
  (fn [{:keys [db] :as cofx} event]
    (-> (update db ::history cons event)
        (handler-fn cofx event))))

(rf/reg-event-fx
  ::your-event
  (save-history
    (fn [{:keys [db]} [_ arg1]]
      {:db (update :count inc)
       :fx [[::alert "hello"]]})))

emccue 2021-05-16T15:40:21.489200Z

and then the history is in your app db

emccue 2021-05-16T15:40:59.489800Z

an interceptor can accomplish the same as the decorator

emccue 2021-05-16T15:42:41.490200Z

and you can also have just an atom for this seperate from your app-db

emccue 2021-05-16T15:43:21.490900Z

then you can probably lookup the functions for each handler and call them and only take the updates to db

emccue 2021-05-16T15:43:44.491400Z

(which is a lot easier to do if you only ever use reg-event-fx and return :db and :fx)

emccue 2021-05-16T15:44:44.492100Z

if there is no native re-frame way to lookup the function registered for an event you can also just write that yourself

emccue 2021-05-16T15:44:50.492300Z

psuedocode:

emccue 2021-05-16T15:50:46.497200Z

(def events (atom '()))
(def handlers (atom {}))

(defmacro register-event ;; Use the opportunity to teach re-frame english
  [event-key handler]
  (rf/reg-event-fx
    ~event-key
    [(... interceptor or wtvr that will add to events, maybe through an fx...)]
    ~handler))
    
    
(register-event 
  ::thing
  (fn [{:keys [db]} [_ arg1]]
    {:db (update :count inc)
     :fx [[::alert "hello"]]}))

;; fold over events
(reduce (fn [db event] (:db ((@handlers (first event)) db))
        {}
        @events)

Richie 2021-05-16T16:50:23.499500Z

@emccue Thanks for the suggestion. I’m still digesting it.

emccue 2021-05-16T16:56:53.000500Z

its not something i would probably do in my own app - re-frisk and re-frame-10x handle event replay well enough for me not to think about it