mirror of
https://github.com/status-im/re-frame.git
synced 2025-02-23 07:18:22 +00:00
commit
f22dc3dc9f
13
CHANGES.md
13
CHANGES.md
@ -1,3 +1,9 @@
|
||||
## 0.8.1 (2016.08.XX) Unreleased
|
||||
|
||||
|
||||
#### Improvements
|
||||
|
||||
- [#200](https://github.com/Day8/re-frame/pull/200) Remove trailing spaces from console logging
|
||||
|
||||
## 0.8.0 (2016.08.19)
|
||||
|
||||
@ -45,10 +51,11 @@ Joking aside, this is a substantial release which will change how you use re-fra
|
||||
At this point, the todomvc example represents the best tutorial on the subject:
|
||||
https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs
|
||||
|
||||
- there's now three kinds of event handlers: `-db`, `-fx` and `-ctx`. <br>
|
||||
- re-frame now supports the notion of Event Handlers accepting coeffects and returning effects. <br>
|
||||
There's now three kinds of event handlers: `-db`, `-fx` and `-ctx`. <br>
|
||||
For a tutorial see: https://github.com/Day8/re-frame/tree/develop/docs <br>
|
||||
|
||||
For examples, see:
|
||||
For Effect Handler examples see:
|
||||
|
||||
1. https://github.com/Day8/re-frame-http-fx
|
||||
2. https://github.com/Day8/re-frame-forward-events-fx
|
||||
@ -177,7 +184,7 @@ Breaking:
|
||||
into the one console group, which could lead to exceptions being hidden (down in a closed group).
|
||||
|
||||
Improvements:
|
||||
- added one tick of extra pause when events have `:flush=dom` metadata. Previously, there were odd times when
|
||||
- added one tick of extra pause when events have `:flush-dom` metadata. Previously, there were odd times when
|
||||
the pause wasn't long enough to ensure redraws.
|
||||
- now compatible with Reagent 0.6.0 (but this not fully tested) while remaining backwards compatible with
|
||||
Reagent v0.5.1
|
||||
|
@ -108,7 +108,7 @@ And here's more carnage:
|
||||
```
|
||||
|
||||
Again, this approach will work. But that dirty great big side-effect doesn't come
|
||||
for free. Its like a muddy monster truck has shown up in our field of white tulips.
|
||||
for free. It's like a muddy monster truck has shown up in our field of white tulips.
|
||||
|
||||
### Bad, Why?
|
||||
|
||||
@ -353,10 +353,10 @@ data from arguments.
|
||||
|
||||
`-db` handlers and `-fx` handlers are conceptually the same. They only differ numerically.
|
||||
|
||||
`-db` handlers take ONE coeeffect called `db`, and they return only ONE effect (db again).
|
||||
`-db` handlers take ONE coeffect called `db`, and they return only ONE effect (db again).
|
||||
|
||||
Whereas `-fx` handlers take potentially MANY coeffects (a map of them) and they return
|
||||
potentially MANY effects (a map of them). So, One vs Many.
|
||||
potentially MANY effects (a map of them). So, One vs Many.
|
||||
|
||||
Just to be clear, the following two handlers achieve the same thing:
|
||||
```clj
|
||||
@ -381,7 +381,7 @@ can. The `-fx` version is more flexible, so it will sometimes have its place.
|
||||
|
||||
90% of the time, simple `-db` handlers are the right tool to use.
|
||||
|
||||
But about 10% of the time, our handlers need additional inputs (coeffecs) or they need to
|
||||
But about 10% of the time, our handlers need additional inputs (coeffects) or they need to
|
||||
cause additional side-effects (effects). That's when you reach for `-fx` handlers.
|
||||
|
||||
`-fx` handlers allow us to return effects, declaratively in data.
|
||||
@ -389,4 +389,3 @@ cause additional side-effects (effects). That's when you reach for `-fx` handle
|
||||
In the next tutorial, we'll shine a light on `interceptors` which are
|
||||
the mechanism by which event handlers are executed. That knowledge will give us a springboard
|
||||
to then, as a next step, better understand coeffects and effects. We'll soon be writing our own.
|
||||
|
||||
|
@ -36,7 +36,7 @@ Flowing" story promoted by re-frame.
|
||||
So, you'll want to use Interceptors because they solve problems, and help you to write nice code.
|
||||
|
||||
__Second__, under the covers, Interceptors provide the mechanism by which
|
||||
event handlers are executed (when you `dispatch`). You they are central concept.
|
||||
event handlers are executed (when you `dispatch`). They are a central concept.
|
||||
|
||||
### What Do Interceptors Do?
|
||||
|
||||
@ -45,7 +45,7 @@ They wrap.
|
||||
Specifically, they wrap event handlers.
|
||||
|
||||
Imagine your event handler is like a piece of ham. An interceptor would be
|
||||
like bread either side of your ham, which makes a sandwich.
|
||||
like bread on either side of your ham, which makes a sandwich.
|
||||
|
||||
And two Interceptors, in a chain, would be like you put another
|
||||
pair of bread slices around the outside of the existing sandwich to make
|
||||
@ -55,7 +55,7 @@ Interceptors wrap on both sides of a handler, layer after layer.
|
||||
|
||||
### Wait, I know That Pattern!
|
||||
|
||||
Interceptors implement middleware. But differently.
|
||||
Interceptors implement middleware. But differently.
|
||||
|
||||
Traditional middleware - often seen in web servers - creates a data
|
||||
processing pipeline via the nested composition of higher order functions.
|
||||
@ -154,7 +154,7 @@ That's it. That's how an event gets handled.
|
||||
Some data called a `context` is threaded through all the calls.
|
||||
|
||||
This value is passed as the argument to every `:before` and `:after`
|
||||
function and they returned it, possibly modified.
|
||||
function and it is returned by each function, possibly modified.
|
||||
|
||||
A `context` is a map with this structure:
|
||||
```clj
|
||||
@ -189,7 +189,7 @@ DataScript connection. Interceptors can build up `:coeffects`, via their
|
||||
|
||||
Equally, some interceptors in the chain will have `:after` functions
|
||||
which process the side effects accumulated into `:effects`
|
||||
including but, not limited to, updates to app-db.
|
||||
including, but not limited to, updates to app-db.
|
||||
|
||||
### Self Modifying
|
||||
|
||||
@ -223,7 +223,7 @@ If our components did this:
|
||||
|
||||
We'd have to write this handler:
|
||||
```clj
|
||||
(def-event-db
|
||||
(reg-event-db
|
||||
:delete-item
|
||||
(fn
|
||||
[db [_ key-to-delete]] ;; <---- Arrgggghhh underscore
|
||||
@ -239,7 +239,7 @@ What a relief it would be to get rid of it, but how? We'll write an interceptor:
|
||||
|
||||
Once we have written `trim-event`, our registration will change to look like this:
|
||||
```clj
|
||||
(def-event-db
|
||||
(reg-event-db
|
||||
:delete-item
|
||||
[trim-event] ;; <--- interceptor added
|
||||
(fn
|
||||
|
@ -64,7 +64,7 @@ To make this happen, we first switch to
|
||||
using `reg-event-fx` (instead of `reg-event-db`).
|
||||
|
||||
Event handlers registered via `reg-event-fx` are slightly
|
||||
different to those registered via `reg-event-fx`. `-fx` handlers
|
||||
different to those registered via `reg-event-db`. `-fx` handlers
|
||||
get two arguments, but the first is not `db`. Instead it
|
||||
is an argument which we will call `cofx` (that's a nice distinct
|
||||
name which will aid communication).
|
||||
@ -121,7 +121,7 @@ to our event handler (`cofx`).
|
||||
|
||||
### `inject-cofx`
|
||||
|
||||
`inject-cofx` is part of re-frame API.
|
||||
`inject-cofx` is part of the re-frame API.
|
||||
|
||||
It is a function which returns an Interceptor whose `:before` function loads
|
||||
a key/value pair into a `context's` `:coeffect` map.
|
||||
@ -159,7 +159,7 @@ Each `cofx-id` requires a different action.
|
||||
|
||||
This function is also part of the re-frame API.
|
||||
|
||||
It allows you associate a`cofx-id` (like `:now` or `:local-store`) with a
|
||||
It allows you to associate a`cofx-id` (like `:now` or `:local-store`) with a
|
||||
handler function that injects the right key/value pair.
|
||||
|
||||
The function you register will be passed two arguments:
|
||||
@ -227,7 +227,7 @@ registration functions and have them auto insert the DataScript connection.
|
||||
|
||||
### Testing
|
||||
|
||||
During testing, you may want to stub out certain coeffets.
|
||||
During testing, you may want to stub out certain coeffects.
|
||||
|
||||
You may, for example, want to test that an event handler works
|
||||
using a specific `now`, not a true random number.
|
||||
@ -240,7 +240,7 @@ In your test, you'd mock out the cofx handler:
|
||||
(assoc coeffects :now (js/Date. 2016 1 1))) ;; now was then
|
||||
```
|
||||
|
||||
If your test does alter registered coeffect handlers, and you are using `cljs.test`,
|
||||
If your test does alter registered coeffect handlers, and you are using `cljs.test`,
|
||||
then you can use a `fixture` to restore all coeffects at the end of your test:
|
||||
```clj
|
||||
(defn re-frame-fixture
|
||||
|
@ -2,7 +2,7 @@
|
||||
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||
[org.clojure/clojurescript "1.9.89"]
|
||||
[reagent "0.6.0-rc"]
|
||||
[re-frame "0.8.0-SNAPSHOT"]
|
||||
[re-frame "0.8.0"]
|
||||
[binaryage/devtools "0.8.1"]
|
||||
[secretary "1.2.3"]]
|
||||
|
||||
|
@ -20,14 +20,14 @@
|
||||
(make-chain interceptors)
|
||||
(do ;; do a whole lot of development time checks
|
||||
(when-not (coll? interceptors)
|
||||
(console :error "re-frame: when registering " id ", expected a collection of interceptors, got: " interceptors))
|
||||
(console :error (str "re-frame: when registering " id ", expected a collection of interceptors, got:") interceptors))
|
||||
(let [chain (make-chain interceptors)]
|
||||
(when (empty? chain)
|
||||
(console :error "re-frame: when registering " id ", given an empty interceptor chain"))
|
||||
(console :error (str "re-frame: when registering" id ", given an empty interceptor chain")))
|
||||
(when-let [not-i (first (remove interceptor/interceptor? chain))]
|
||||
(if (fn? not-i)
|
||||
(console :error "re-frame: when registering " id ", got a function instead of an interceptor. Did you provide old style middleware by mistake? Got: " not-i)
|
||||
(console :error "re-frame: when registering " id ", expected interceptors, but got: " not-i)))
|
||||
(console :error (str "re-frame: when registering " id ", got a function instead of an interceptor. Did you provide old style middleware by mistake? Got:") not-i)
|
||||
(console :error (str "re-frame: when registering " id ", expected interceptors, but got:") not-i)))
|
||||
chain)))))
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@
|
||||
(let [event-id (first-in-vector event-v)]
|
||||
(if-let [interceptors (get-handler kind event-id true)]
|
||||
(if *handling*
|
||||
(console :error "re-frame: while handling \"" *handling* "\" dispatch-sync was called for \"" event-v "\". You can't call dispatch-sync within an event handler.")
|
||||
(console :error (str "re-frame: while handling \"" *handling* "\", dispatch-sync was called for \"" event-v "\". You can't call dispatch-sync within an event handler."))
|
||||
(binding [*handling* event-v]
|
||||
(interceptor/execute event-v interceptors))))))
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
(fn [value]
|
||||
(doseq [{:keys [ms dispatch] :as effect} value]
|
||||
(if (or (empty? dispatch) (-> ms number? not))
|
||||
(console :error "re-frame: ignoring bad :dispatch-later value: " effect)
|
||||
(console :error "re-frame: ignoring bad :dispatch-later value:" effect)
|
||||
(set-timeout! #(router/dispatch dispatch) ms)))))
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@
|
||||
:dispatch
|
||||
(fn [value]
|
||||
(if-not (vector? value)
|
||||
(console :error "re-frame: ignoring bad :dispatch value. Expected a vector, but got: " value)
|
||||
(console :error "re-frame: ignoring bad :dispatch value. Expected a vector, but got:" value)
|
||||
(router/dispatch value))))
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@
|
||||
:dispatch-n
|
||||
(fn [value]
|
||||
(if-not (sequential? value)
|
||||
(console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got: " value))
|
||||
(console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got:" value))
|
||||
(doseq [event value] (router/dispatch event))))
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
(if-let [unknown-keys (seq (clojure.set/difference
|
||||
(-> (dissoc m :name) keys set) ;; XXX take out name in due course
|
||||
mandatory-interceptor-keys))]
|
||||
(console :error "re-frame: ->interceptor " m " has unknown keys: " unknown-keys)))
|
||||
(console :error "re-frame: ->interceptor " m " has unknown keys:" unknown-keys)))
|
||||
{:id (or id name :unnamed) ;; XXX remove `name` in due course
|
||||
:before before
|
||||
:after after })
|
||||
|
@ -28,7 +28,7 @@
|
||||
(let [handler (get-handler kind id)]
|
||||
(when debug-enabled?
|
||||
(when (and required? (nil? handler))
|
||||
(console :error "re-frame: no " (str kind) " handler registered for: " id)))
|
||||
(console :error "re-frame: no " (str kind) " handler registered for:" id)))
|
||||
handler)))
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
[kind id handler-fn]
|
||||
(when debug-enabled?
|
||||
(when (get-handler kind id false)
|
||||
(console :warn "re-frame: overwriting " (str kind) " handler for: " id))) ;; allow it, but warn. Happens on figwheel reloads.
|
||||
(console :warn "re-frame: overwriting" (str kind) "handler for:" id))) ;; allow it, but warn. Happens on figwheel reloads.
|
||||
(swap! kind->id->handler assoc-in [kind id] handler-fn)
|
||||
handler-fn) ;; note: returns the just registered handler
|
||||
|
||||
@ -53,4 +53,4 @@
|
||||
(assert (kinds kind))
|
||||
(if (get-handler kind id)
|
||||
(swap! kind->id->handler update-in [kind] dissoc id)
|
||||
(console :warn "re-frame: can't clear " (str kind) " handler for " id ". Not found."))))
|
||||
(console :warn "re-frame: can't clear" (str kind) "handler for" (str id ". Handler not found.")))))
|
||||
|
@ -102,13 +102,13 @@
|
||||
;; register a callback function which will be called after each event is processed
|
||||
(add-post-event-callback [_ id callback-fn]
|
||||
(if (contains? post-event-callback-fns id)
|
||||
(console :warn "re-frame: overwriting existing post event call back with id: " id))
|
||||
(console :warn "re-frame: overwriting existing post event call back with id:" id))
|
||||
(->> (assoc post-event-callback-fns id callback-fn)
|
||||
(set! post-event-callback-fns)))
|
||||
|
||||
(remove-post-event-callback [_ id]
|
||||
(if-not (contains? post-event-callback-fns id)
|
||||
(console :warn "re-frame: could not remove post event call back with id: " id)
|
||||
(console :warn "re-frame: could not remove post event call back with id:" id)
|
||||
(->> (dissoc post-event-callback-fns id)
|
||||
(set! post-event-callback-fns))))
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
:id :debug
|
||||
:before (fn debug-before
|
||||
[context]
|
||||
(console :log "Handling re-frame event: " (get-coeffect context :event))
|
||||
(console :log "Handling re-frame event:" (get-coeffect context :event))
|
||||
context)
|
||||
:after (fn debug-after
|
||||
[context]
|
||||
@ -37,15 +37,15 @@
|
||||
orig-db (get-coeffect context :db)
|
||||
new-db (get-effect context :db ::not-found)]
|
||||
(if (= new-db ::not-found)
|
||||
(console :log "No :db changes caused by: " event)
|
||||
(console :log "No :db changes caused by:" event)
|
||||
(let [[only-before only-after] (data/diff orig-db new-db)
|
||||
db-changed? (or (some? only-before) (some? only-after))]
|
||||
(if db-changed?
|
||||
(do (console :group "db clojure.data/diff for: " event)
|
||||
(console :log "only before: " only-before)
|
||||
(console :log "only after : " only-after)
|
||||
(do (console :group "db clojure.data/diff for:" event)
|
||||
(console :log "only before:" only-before)
|
||||
(console :log "only after :" only-after)
|
||||
(console :groupEnd))
|
||||
(console :log "no app-db changes caused by: " event))))
|
||||
(console :log "no app-db changes caused by:" event))))
|
||||
context))))
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
(let [cache-key [query-v dynv]]
|
||||
;; when this reaction is nolonger being used, remove it from the cache
|
||||
(add-on-dispose! r #(do (swap! query->reaction dissoc cache-key)
|
||||
#_(console :log "Removing subscription: " cache-key)))
|
||||
#_(console :log "Removing subscription:" cache-key)))
|
||||
;; cache this reaction, so it can be used to deduplicate other, later "=" subscriptions
|
||||
(swap! query->reaction assoc cache-key r)
|
||||
r)) ;; return the actual reaction
|
||||
@ -60,7 +60,7 @@
|
||||
handler-fn (get-handler kind query-id)]
|
||||
;(console :log "Subscription created: " query-v)
|
||||
(if-not handler-fn
|
||||
(console :error "re-frame: no subscription handler registered for: \"" query-id "\". Returning a nil subscription."))
|
||||
(console :error (str "re-frame: no subscription handler registered for: \"" query-id "\". Returning a nil subscription.")))
|
||||
(cache-and-return query-v [] (handler-fn app-db query-v)))))
|
||||
|
||||
([v dynv]
|
||||
@ -71,9 +71,9 @@
|
||||
handler-fn (get-handler kind query-id)]
|
||||
(when debug-enabled?
|
||||
(when-let [not-reactive (not-empty (remove ratom? dynv))]
|
||||
(console :warn "re-frame: your subscription's dynamic parameters that don't implement IReactiveAtom: " not-reactive)))
|
||||
(console :warn "re-frame: your subscription's dynamic parameters that don't implement IReactiveAtom:" not-reactive)))
|
||||
(if (nil? handler-fn)
|
||||
(console :error "re-frame: no subscription handler registered for: \"" query-id "\". Returning a nil subscription.")
|
||||
(console :error (str "re-frame: no subscription handler registered for: \"" query-id "\". Returning a nil subscription."))
|
||||
(let [dyn-vals (make-reaction (fn [] (mapv deref dynv)))
|
||||
sub (make-reaction (fn [] (handler-fn app-db v @dyn-vals)))]
|
||||
;; handler-fn returns a reaction which is then wrapped in the sub reaction
|
||||
@ -144,7 +144,7 @@
|
||||
;; a single `inputs` fn
|
||||
1 (let [f (first input-args)]
|
||||
(when-not (fn? f)
|
||||
(console :error err-header "2nd argument expected to be an inputs function, got: " f))
|
||||
(console :error err-header "2nd argument expected to be an inputs function, got:" f))
|
||||
f)
|
||||
|
||||
;; one sugar pair
|
||||
@ -158,7 +158,7 @@
|
||||
vecs (map last pairs)
|
||||
ret-val (map subscribe vecs)]
|
||||
(when-not (every? vector? vecs)
|
||||
(console :error err-header "expected pairs of :<- and vectors, got: " pairs))
|
||||
(console :error err-header "expected pairs of :<- and vectors, got:" pairs))
|
||||
(fn inp-fn
|
||||
([_] ret-val)
|
||||
([_ _] ret-val))))]
|
||||
|
@ -7,5 +7,5 @@
|
||||
[v]
|
||||
(if (vector? v)
|
||||
(first v)
|
||||
(console :error "re-frame: expected a vector, but got: " v)))
|
||||
(console :error "re-frame: expected a vector, but got:" v)))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user