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.
Sorry, I haven’t formed a question yet. I’m thinking this through and looking for guidance.
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.
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.
@rgkirch In your event handlers you can always just do this
(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"]]})))
and then the history is in your app db
an interceptor can accomplish the same as the decorator
and you can also have just an atom for this seperate from your app-db
then you can probably lookup the functions for each handler and call them and only take the updates to db
(which is a lot easier to do if you only ever use reg-event-fx and return :db and :fx)
if there is no native re-frame way to lookup the function registered for an event you can also just write that yourself
psuedocode:
(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)
@emccue Thanks for the suggestion. I’m still digesting it.
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