Fork me on GitHub
#re-frame
<
2021-05-16
>
Richie14:05:09

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.

Richie14:05:43

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

Richie15:05:48

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.

Richie15:05:53

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.

emccue15:05:14

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

emccue15:05:58

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

emccue15:05:21

and then the history is in your app db

emccue15:05:59

an interceptor can accomplish the same as the decorator

emccue15:05:41

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

emccue15:05:21

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

emccue15:05:44

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

emccue15:05:44

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

emccue15:05:50

psuedocode:

emccue15:05:46

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

Richie16:05:23

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

emccue16:05:53

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