re-frame
re-frame copied to clipboard
Adds function to simplify creating new event types
Adds the function reg-event to re-frame.core which takes a handling interceptor instead of a handler as its last argument. This makes it easier to create event registering functions with all standard interceptors added to the chain, even if changes are made to the standard interceptor chain.
reg-event-db, -fx and -ctx now wrap reg-event, passing their interceptor wrapped handlers.
This is a suggestion to make creating custom event types a tiny bit easier.
Here's an example use case. Let's say we want to catch exceptions and add exception traces. If we don't want to add the standard chain ourselves (adds maintenance risk, although a low risk as this isn't code that changes often), right now we could write this as:
(defn- interceptor->with-exception-tracing [f]
(fn [context]
(try (f context)
(catch :default e
(trace/merge-trace! {:tags {:exception e}})
(throw e)))))
(defn- wrap-exception-interceptor
[id]
(let [interceptors (into [] (get-in @registrar/kind->id->handler [:event id]))
last-interceptor (peek interceptors)
wrapped-interceptor (update last-interceptor :before interceptor->with-exception-tracing)]
(swap! registrar/kind->id->handler assoc-in [:event id]
(conj (pop interceptors) wrapped-interceptor))))
(defn my-reg-event-db
([id handler]
(my-reg-event-db id nil handler))
([id interceptors handler]
(re-frame/reg-event-db id interceptors handler)
(wrap-exception-interceptor id)))
If we don't mind adding the interceptors ourselves, we could shorten this a bit, but this adds some risk that changes to the standard interceptor chain aren't caught, and the event will act in a non-standard way:
(defn my-reg-event-db
([id handler]
(my-reg-event-db id nil handler))
([id interceptors handler]
(events/register id [cofx/inject-db fx/do-fx inject-global-interceptors interceptors
(-> handler
std-interceptors/db-handler->interceptor
(update :before interceptor->with-exception-tracing))])))
With the suggested edit the final registration is simpler:
(defn my-reg-event-db
([id handler]
(my-reg-event-db id nil handler))
([id interceptors handler]
(re-frame/reg-event id interceptors
(-> handler
std-interceptors/db-handler->interceptor
(update :before interceptor->with-exception-tracing)))))
Might not be a huge difference, but it feels a bit more ergonomic. And if changes are made to the standard interceptor chain, they are only made in one place.