re-frame/src/re_frame/cofx.cljc

69 lines
2.1 KiB
Clojure

(ns re-frame.cofx
(:require
[re-frame.db :refer [app-db]]
[re-frame.interceptor :refer [->interceptor]]
[re-frame.registrar :refer [get-handler clear-handlers register-handler]]
[re-frame.loggers :refer [console]]))
;; -- Registration ------------------------------------------------------------
(def kind :cofx)
(assert (re-frame.registrar/kinds kind))
(def register (partial register-handler kind))
;; -- Interceptor -------------------------------------------------------------
(defn inject-cofx
"Returns an interceptor which adds to a `context's` `:coeffects`.
`coeffects` are the input resources required by an event handler
to perform its job. The two most obvious ones are `db` and `event`.
But sometimes a handler might need other resources.
Perhaps a handler needs a random number or a GUID or the current datetime.
Perhaps it needs access to the connection to a DataScript database.
If the handler directly access these resources, it stops being as
pure. It immedaitely becomes harder to test, etc.
So the necessary resources are \"injected\" into the `coeffect` (map)
given the handler.
Given an `id`, and an optional value, lookup the registered coeffect
handler (previously registered via `reg-cofx`) and it with two arguments:
the current value of `:coeffects` and, optionally, the value. The registered handler
is expected to return a modified coeffect.
"
([id]
(->interceptor
:id :coeffects
:before (fn coeffects-before
[context]
(update context :coeffects (get-handler kind id)))))
([id value]
(->interceptor
:id :coeffects
:before (fn coeffects-before
[context]
(update context :coeffects (get-handler kind id) value)))))
;; -- Builtin CoEffects Handlers ---------------------------------------------
;; :db
;;
;; Adds to coeffects the value in `app-db`, under the key `:db`
(register
:db
(fn db-coeffects-handler
[coeffects]
(assoc coeffects :db @app-db)))
;; Because this interceptor is used so much, we reify it
(def inject-db (inject-cofx :db))