re-frame/src/re_frame/fx.cljc

123 lines
3.4 KiB
Plaintext
Raw Normal View History

(ns re-frame.fx
(:require
[re-frame.router :as router]
[re-frame.db :refer [app-db]]
2016-08-08 05:17:01 +00:00
[re-frame.interceptor :refer [->interceptor]]
[re-frame.interop :refer [set-timeout!]]
[re-frame.events :as events]
[re-frame.registrar :refer [get-handler clear-handlers register-handler]]
[re-frame.loggers :refer [console]]))
;; -- Registration ------------------------------------------------------------
2016-07-13 14:32:36 +00:00
(def kind :fx)
(assert (re-frame.registrar/kinds kind))
2016-08-08 05:17:01 +00:00
(def register (partial register-handler kind))
2016-07-13 14:32:36 +00:00
2016-08-08 05:17:01 +00:00
;; -- Interceptor -------------------------------------------------------------
(def do-fx
2016-08-13 03:17:47 +00:00
"An interceptor which actions a `context's` (side) `:effects`.
2016-08-13 03:17:47 +00:00
For each key in the `:effects` map, call the `effects handler` previously
registered using `reg-fx`.
2016-08-08 05:17:01 +00:00
So, if `:effects` was:
{:dispatch [:hello 42]
:db {...}
:undo \"set flag\"}
call the registered effects handlers for each of the map's keys:
`:dispatch`, `:undo` and `:db`."
(->interceptor
2016-08-23 12:47:22 +00:00
:id :do-fx
:after (fn do-fx-after
[context]
(doseq [[effect-k value] (:effects context)]
(if-let [effect-fn (get-handler kind effect-k true)]
(effect-fn value))))))
2016-08-08 05:17:01 +00:00
2016-08-13 03:17:47 +00:00
;; -- Builtin Effect Handlers ------------------------------------------------
;; :dispatch-later
;;
2016-08-13 03:17:47 +00:00
;; `dispatch` one or more events after given delays. Expects a collection
;; of maps with two keys: :`ms` and `:dispatch`
;;
;; usage:
;;
;; {:dispatch-later [{:ms 200 :dispatch [:event-id "param"]} ;; in 200ms do this: (dispatch [:event-id "param"])
;; {:ms 100 :dispatch [:also :this :in :100ms]}]}
;;
(register
:dispatch-later
2016-08-13 03:17:47 +00:00
(fn [value]
2016-08-23 12:47:22 +00:00
(doseq [{:keys [ms dispatch] :as effect} value]
(if (or (empty? dispatch) (not (number? ms)))
(console :error "re-frame: ignoring bad :dispatch-later value:" effect)
2016-07-27 12:26:22 +00:00
(set-timeout! #(router/dispatch dispatch) ms)))))
;; :dispatch
;;
;; `dispatch` one event. Excepts a single vector.
;;
;; usage:
;; {:dispatch [:event-id "param"] }
(register
:dispatch
2016-08-13 03:17:47 +00:00
(fn [value]
(if-not (vector? value)
(console :error "re-frame: ignoring bad :dispatch value. Expected a vector, but got:" value)
2016-08-13 03:17:47 +00:00
(router/dispatch value))))
;; :dispatch-n
;;
;; `dispatch` more than one event. Expects a list or vector of events. Something for which
;; sequential? returns true.
;;
;; usage:
;; {:dispatch-n (list [:do :all] [:three :of] [:these])}
;;
(register
:dispatch-n
2016-08-13 03:17:47 +00:00
(fn [value]
(if-not (sequential? value)
(console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got:" value))
2016-08-13 03:17:47 +00:00
(doseq [event value] (router/dispatch event))))
;; :deregister-event-handler
;;
2016-08-13 03:17:47 +00:00
;; removes a previously registered event handler. Expects either a single id (
;; typically a keyword), or a seq of ids.
;;
;; usage:
2016-08-13 03:17:47 +00:00
;; {:deregister-event-handler :my-id)}
;; or:
2016-08-13 03:17:47 +00:00
;; {:deregister-event-handler [:one-id :another-id]}
;;
2016-07-13 14:32:36 +00:00
(register
:deregister-event-handler
2016-08-13 03:17:47 +00:00
(fn [value]
(let [clear-event (partial clear-handlers events/kind)]
2016-08-13 03:17:47 +00:00
(if (sequential? value)
2016-08-23 12:47:22 +00:00
(doseq [event (if (sequential? value) value [value])]
(clear-event event))))))
2016-07-13 14:32:36 +00:00
2016-08-13 03:17:47 +00:00
;; :db
;;
;; reset! app-db with a new value. Expects a map.
;;
;; usage:
;; {:db {:key1 value1 key2 value2}}
;;
(register
:db
2016-08-13 03:17:47 +00:00
(fn [value]
(reset! app-db value)))