From a5118746911e408c502a8850be5f8b181dd96b5e Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Tue, 20 Dec 2016 23:02:13 +1100 Subject: [PATCH 01/33] Fix up Navigation Links --- docs/EventHandlingInfographic.md | 2 +- docs/Interceptors.md | 28 ++++++++++++++-------------- docs/MentalModelOmnibus.md | 2 +- docs/README.md | 1 - docs/SubscriptionFlow.md | 2 +- docs/SubscriptionInfographic.md | 8 ++++++-- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/docs/EventHandlingInfographic.md b/docs/EventHandlingInfographic.md index 046a8778d..b331976fb 100644 --- a/docs/EventHandlingInfographic.md +++ b/docs/EventHandlingInfographic.md @@ -11,6 +11,6 @@ They should be reviewed in conjunction with the written tutorials. *** - +Previous: [Mental Model Omnibus](MentalModelOmnibus.md)       Up: [Index](README.md)       Next: [Effectful Handlers](EffectfulHandlers.md)       diff --git a/docs/Interceptors.md b/docs/Interceptors.md index ce51884aa..d5db3968f 100644 --- a/docs/Interceptors.md +++ b/docs/Interceptors.md @@ -1,8 +1,10 @@ ## re-frame Interceptors +This is a tutorial on re-frame Interceptors. It explains exactly how events get handled. + -## Table Of Contents +### Table Of Contents - [Introduction](#introduction) - [Interceptors](#interceptors) @@ -25,12 +27,8 @@ -## Introduction - -This is a tutorial on re-frame Interceptors. -## Interceptors -### Why Interceptors? +## Why Interceptors? Two reasons. @@ -45,7 +43,7 @@ So, you'll want to use Interceptors because they solve problems, and help you to __Second__, under the covers, Interceptors provide the mechanism by which event handlers are executed (when you `dispatch`). They are a central concept. -### What Do Interceptors Do? +## What Do Interceptors Do? They wrap. @@ -60,7 +58,7 @@ a sandwich of the sandwich. Now it is a very thick sandwich. Interceptors wrap on both sides of a handler, layer after layer. -### Wait, I know That Pattern! +## Wait, I know That Pattern! Interceptors implement middleware. But differently. @@ -77,7 +75,7 @@ and then backwards along the same chain. Because the interceptor pipeline is composed via data, rather than higher order functions, it is a more flexible arrangement. -### What's In The Pipeline? +## What's In The Pipeline? Data. It flows through the pipeline being progressively transformed. @@ -94,7 +92,7 @@ In re-frame, the forwards sweep progressively creates the `coeffects` I'll pause while you read that sentence again. That's the key concept, right there. -### Show Me +## Show Me At the time when you register an event handler, you can provide a chain of interceptors too. @@ -109,20 +107,22 @@ Using a 3-arity registration function: > Each Event Handler can have its own tailored interceptor chain, provided at registration-time. -### Handlers Are Interceptors Too +## Handlers Are Interceptors Too -You might see that registration above as associating `:some-id` with two things: (1) a chain of 2 interceptors `[in1 in2]` +You might see that registration above as associating `:some-id` with +two things: (1) a chain of 2 interceptors `[in1 in2]` and (2) a handler. Except, the handler is turned into an interceptor too (we'll see how shortly). So `:some-id` is only associated with one thing: a 3-chain of interceptors, -with the handler wrapped in an interceptor, called say `h`, and put on the end of the other two: `[in1 in2 h]`. +with the handler wrapped in an interceptor, called say `h`, and put on the +end of the other two: `[in1 in2 h]`. Except, the registration function itself, `reg-event-db`, actually takes this 3-chain and inserts its own standard interceptors, called say `std1` and `std2` (which do useful things, more soon) at the front, -so ACTUALLY, there's about 5 interceptors in the chain: `[std1 std2 in1 in2 h]` +so **ACTUALLY**, there's about 5 interceptors in the chain: `[std1 std2 in1 in2 h]` So, ultimately, that event registration associates the event id `:some-id` with __just__ a chain of interceptors. Nothing more. diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index 94275a038..5e53880fd 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -307,7 +307,7 @@ Your love for re-frame will be deep, abiding and enriching. Previous: [First Code Walk-Through](CodeWalkthrough.md)       Up: [Index](README.md)       -Next: [Effectful Handlers](EffectfulHandlers.md) +Next: [Infographic Overview](EventHandlingInfographic.md) [SPAs]:http://en.wikipedia.org/wiki/Single-page_application diff --git a/docs/README.md b/docs/README.md index 2e5827a82..51717e279 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,7 +16,6 @@ ### Subscriptions -- [TodoMVC annotated example](https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs) - [Infographic](SubscriptionInfographic.md) - [Correcting a wrong](SubscriptionsCleanup.md) - [Flow Mechanics](SubscriptionFlow.md) diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index bcfca98e5..110a3e833 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -209,7 +209,7 @@ On with the rest of my lies and distortions... *** -Previous: [Flow Mechanics](SubscriptionFlow.md)       +Previous: [Correcting a wrong](SubscriptionsCleanup.md)       Up: [Index](README.md)       Next: [Basic App Structure](Basic-App-Structure.md)        diff --git a/docs/SubscriptionInfographic.md b/docs/SubscriptionInfographic.md index 20498192c..271b81e64 100644 --- a/docs/SubscriptionInfographic.md +++ b/docs/SubscriptionInfographic.md @@ -1,8 +1,12 @@ -## Subscription Infographics +## Subscription Infographic -Before studying this infographic, be sure you have read the +There's two things to do here. + +**First**, please read through the annotated subscription code [in the todomvc example](https://github.com/Day8/re-frame/blob/master/examples/todomvc/src/todomvc/subs.cljs). +**Then**, look at this Infographic: + *** From 22187ba6ea05b0709471c28eb3039ff83c567f62 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Tue, 20 Dec 2016 23:16:53 +1100 Subject: [PATCH 02/33] Better Table Of Contents --- docs/Basic-App-Structure.md | 14 +++++--------- docs/CodeWalkthrough.md | 3 +-- docs/Coeffects.md | 2 +- docs/EffectfulHandlers.md | 2 +- docs/Effects.md | 2 +- docs/EventHandlingInfographic.md | 2 +- 6 files changed, 10 insertions(+), 15 deletions(-) diff --git a/docs/Basic-App-Structure.md b/docs/Basic-App-Structure.md index c61cda5f4..31a3d692b 100644 --- a/docs/Basic-App-Structure.md +++ b/docs/Basic-App-Structure.md @@ -1,12 +1,3 @@ - - -## Table Of Contents - -- [Simpler Apps](#simpler-apps) - - [There's A Small Gotcha](#theres-a-small-gotcha) -- [Larger Apps](#larger-apps) - - ## Simpler Apps @@ -73,3 +64,8 @@ Continue to [Navigation](Navigation.md) to learn how to switch between panels of Previous: [Correcting a wrong](SubscriptionsCleanup.md)       Up: [Index](README.md)       Next: [Navigation](Navigation.md) + + + + + diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index 501c6e96e..23d9afa7d 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -11,10 +11,9 @@ enough to start coding by yourself. In this tutorial, **we'll look at re-frame code**. - -## Table Of Contents +### Table Of Contents - [What Code?](#what-code) - [What Does It Do?](#what-does-it-do) diff --git a/docs/Coeffects.md b/docs/Coeffects.md index 63f561a5c..156355355 100644 --- a/docs/Coeffects.md +++ b/docs/Coeffects.md @@ -7,7 +7,7 @@ to manage them in tests. -## Table Of Contents +### Table Of Contents - [What Are They?](#what-are-they) - [An Example](#an-example) diff --git a/docs/EffectfulHandlers.md b/docs/EffectfulHandlers.md index 7d246c50b..1453a3ab3 100644 --- a/docs/EffectfulHandlers.md +++ b/docs/EffectfulHandlers.md @@ -5,7 +5,7 @@ Yes, a surprising claim. -## Table Of Contents +### Table Of Contents - [Events Happen](#events-happen) - [Handling The Happening](#handling-the-happening) diff --git a/docs/Effects.md b/docs/Effects.md index 6e0fa6da2..5a19228cd 100644 --- a/docs/Effects.md +++ b/docs/Effects.md @@ -12,7 +12,7 @@ make side effects a noop in event replays. -## Table Of Contents +### Table Of Contents - [Where Effects Come From](#where-effects-come-from) - [The Effects Map](#the-effects-map) diff --git a/docs/EventHandlingInfographic.md b/docs/EventHandlingInfographic.md index b331976fb..160fc9ad1 100644 --- a/docs/EventHandlingInfographic.md +++ b/docs/EventHandlingInfographic.md @@ -1,6 +1,6 @@ ## Event Handling Infographics -Three diagrams are provided: +Three diagrams are provided below: - a beginner's romp - an intermediate schematic depiction - an advanced, full detail rendering From 6df7c0984ebbaef4f08f2773950d02f743cab6a1 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 21 Dec 2016 21:24:32 +1100 Subject: [PATCH 03/33] Add figma file used to create the infographics --- docs/Figma Infographics/inforgraphics.fig | Bin 0 -> 119547 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Figma Infographics/inforgraphics.fig diff --git a/docs/Figma Infographics/inforgraphics.fig b/docs/Figma Infographics/inforgraphics.fig new file mode 100644 index 0000000000000000000000000000000000000000..1bacb100382fe3e8f4135e2c6b57839cbffe66d0 GIT binary patch literal 119547 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 VS(#! Date: Wed, 21 Dec 2016 13:20:36 -0700 Subject: [PATCH 04/33] Add re-frame-datatable to External-Resources.md --- docs/External-Resources.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/External-Resources.md b/docs/External-Resources.md index 1d799a0c7..ff3f02afb 100644 --- a/docs/External-Resources.md +++ b/docs/External-Resources.md @@ -51,6 +51,8 @@ Please add to this list by submitting a pull request. ### Libraries +* [re-frame-datatable](https://github.com/kishanov/re-frame-datatable) - DataTable UI component built for use with re-frame. + * [Stately: State Machines](https://github.com/nodename/stately) also https://www.youtube.com/watch?v=klqorRUPluw ### Videos From 21d151d7c4557898cfaa56d7b89986f4edec35bf Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 22 Dec 2016 20:45:20 +1100 Subject: [PATCH 05/33] Provide more direction to docs readers --- docs/CodeWalkthrough.md | 10 ++++++++-- docs/MentalModelOmnibus.md | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index 23d9afa7d..9c9b3ef76 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -500,10 +500,16 @@ structure exists in `app-db` before any subscriptions or event handlers run. - write and register query functions which implement nodes in a signal graph (query layer) (domino 4) - write Reagent view functions (view layer) (domino 5) -## Further Code +## Next Steps -You should also look at the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc). +You should now take time to carefully review the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc). +After that, you'll be ready to write your own code. Perhaps you will use a +template to create your own project:
+Client only: https://github.com/Day8/re-frame-template
+Full Stack: http://www.luminusweb.net/ + +Obviously you should also go on to read the further documentation. *** diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index 5e53880fd..122070334 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -1,4 +1,8 @@ +> In a rush? You can get away with skipping this page on the first pass.
+> But remember to cycle back to it later. It contains useful insights.
+> Next page: [Effectful Handlers](EffectfulHandlers.md) + ## Mental Model Omnibus > If a factory is torn down but the rationality which produced it is @@ -23,6 +27,8 @@ It is a little rambling, but I'm hoping it will deliver for you at least one "Aaaah, I see" moment before the end. > All models are wrong, but some are useful +
+ From 816a5a0a059a602d0e28f9a8bda0167fcc7cbf42 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 21 Dec 2016 21:24:32 +1100 Subject: [PATCH 06/33] Add figma file used to create the infographics --- docs/Figma Infographics/inforgraphics.fig | Bin 0 -> 119547 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/Figma Infographics/inforgraphics.fig diff --git a/docs/Figma Infographics/inforgraphics.fig b/docs/Figma Infographics/inforgraphics.fig new file mode 100644 index 0000000000000000000000000000000000000000..1bacb100382fe3e8f4135e2c6b57839cbffe66d0 GIT binary patch literal 119547 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 VS(#! Date: Thu, 22 Dec 2016 20:45:20 +1100 Subject: [PATCH 07/33] Provide more direction to docs readers --- docs/CodeWalkthrough.md | 10 ++++++++-- docs/MentalModelOmnibus.md | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index 23d9afa7d..9c9b3ef76 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -500,10 +500,16 @@ structure exists in `app-db` before any subscriptions or event handlers run. - write and register query functions which implement nodes in a signal graph (query layer) (domino 4) - write Reagent view functions (view layer) (domino 5) -## Further Code +## Next Steps -You should also look at the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc). +You should now take time to carefully review the [todomvc example application](https://github.com/Day8/re-frame/tree/develop/examples/todomvc). +After that, you'll be ready to write your own code. Perhaps you will use a +template to create your own project:
+Client only: https://github.com/Day8/re-frame-template
+Full Stack: http://www.luminusweb.net/ + +Obviously you should also go on to read the further documentation. *** diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index 5e53880fd..122070334 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -1,4 +1,8 @@ +> In a rush? You can get away with skipping this page on the first pass.
+> But remember to cycle back to it later. It contains useful insights.
+> Next page: [Effectful Handlers](EffectfulHandlers.md) + ## Mental Model Omnibus > If a factory is torn down but the rationality which produced it is @@ -23,6 +27,8 @@ It is a little rambling, but I'm hoping it will deliver for you at least one "Aaaah, I see" moment before the end. > All models are wrong, but some are useful +
+ From 2f0f406c8964d6cf9be45de86b394a8e223614be Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 22 Dec 2016 21:15:31 +1100 Subject: [PATCH 08/33] Improve docs navigation and remove unnecessary Tables of Contexts --- docs/ApplicationState.md | 23 +++++++++++++---------- docs/Effects.md | 18 +++++++++--------- docs/Solve-the-CPU-hog-problem.md | 19 ++++++------------- docs/The-re-frame-logo.md | 17 ++++++----------- 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/docs/ApplicationState.md b/docs/ApplicationState.md index 6d9609a99..4dc5f038e 100644 --- a/docs/ApplicationState.md +++ b/docs/ApplicationState.md @@ -1,7 +1,9 @@ ## Application State - - +
+ + +
### The Big Ratom @@ -42,7 +44,8 @@ Further Notes: 2. In the documentation and code, I make a distinction between `app-db` (the `ratom`) and `db` which is the (map) `value` currently stored **inside** this `ratom`. Be aware of that naming as you read code. 3. re-frame creates and manages an `app-db` for you, so - you don't need to declare one yourself (see the 1st FAQ if you want to inspect the value it holds). + you don't need to declare one yourself (see the [the first FAQ](FAQs/Inspecting-app-db.md) if you want + to inspect the value it holds). 4. `app-db` doesn't actually have to be a `ratom` containing a map. It could, for example, be a [datascript](https://github.com/tonsky/datascript database). In fact, any database which can signal you when it changes would do. We'd love! to be using [datascript](https://github.com/tonsky/datascript database) - so damn cool - @@ -69,7 +72,7 @@ Again, this simplicity causes a certain class of bugs or design problems to evap so that, at any moment, we can validate all the data in the application. **All of it!** We do this check after every single "event handler" runs (event handlers compute new state). And this enables us to catch errors early (and accurately). It increases confidence in the way -that Types can increase confidence, only [a good schema can provide more +that Types can increase confidence, only [a good schema can potentially provide more **leverage** than types](https://www.youtube.com/watch?v=nqY4nUMfus8). 4. Undo/Redo [becomes straight forward to implement](https://github.com/Day8/re-frame-undo). @@ -91,22 +94,22 @@ source of data is elsewhere. ### Create A Leveragable Schema -You really need a `spec` schema for `app-db`. The derived power is immense. +You need to create a [spec](http://clojure.org/about/spec) schema for `app-db`. You want that leverage. Of course, that means you'll have to learn [spec](http://clojure.org/about/spec) and there's some overhead in that, so maybe, just maybe, in your initial experiments, you can get away without one. But not for long. Promise me you'll write a `spec`. Promise me. Okay, good. -The [todomvc example](https://github.com/Day8/re-frame/tree/master/examples/todomvc) -shows how to use a spec. Look in `src/db.cljs` for the spec itself, and then in `src/events.cljs` for +Soon we'll look at the [todomvc example](https://github.com/Day8/re-frame/tree/master/examples/todomvc) +which shows how to use a spec. (Check out `src/db.cljs` for the spec itself, and then in `src/events.cljs` for how to write code which checks `app-db` against this spec after every single event has been -processed. +processed.) -Specs are more leveragable than types. This is a big interesting idea which is not yet mainstream. +Specs are potentially more leveragable than types. This is a big interesting idea which is not yet mainstream. Watch how:
https://www.youtube.com/watch?v=VNTQ-M_uSo8 -Also, the mighty Rich Hickey (poor audio):
+Also, watch the mighty Rich Hickey (poor audio):
https://vimeo.com/195711510 ### How do I inspect it? diff --git a/docs/Effects.md b/docs/Effects.md index 5a19228cd..1a9ade204 100644 --- a/docs/Effects.md +++ b/docs/Effects.md @@ -54,18 +54,18 @@ Like this: An effects map contains instructions. -Each key/value pair in the map is one instruction - the `key` uniquely identifies -the particular side effect required, and the `value` for that `key` provides -further data. The structure of `value` is different for each side-effect. +Each key/value pair in the map is one instruction - the `key` uniquely identifies +the particular side effect required, and the `value` for that `key` provides +further data. The structure of `value` is different for each side-effect. -Here's the two instructions from the example above: +Here's the two instructions from the example above: ```cljs {:db (assoc db :flag a) ;; side effect on app-db :dispatch [:do-something-else 3]} ;; dispatch this event ``` The `:db` `key` instructs that "app-db" should be `reset!` to the -`value` supplied. +`value` supplied. And the `:dispatch` `key` instructs that an event should be dispatched. The `value` is the vector to dispatch. @@ -73,19 +73,19 @@ dispatched. The `value` is the vector to dispatch. There's many other possible effects, like for example `:dispatch-later` or `:set-local-store`. -And so on. And so on. Which brings us to a problem. +And so on. And so on. Which brings us to a problem. ### Infinite Effects -While re-frame supplies a number of builtin effects, the set of +While re-frame supplies a number of builtin effects, the set of possible effects is open ended. -What if you use PostgreSQL and want an effect which issues mutating +What if you use PostgreSQL and want an effect which issues mutating queries? Or what if you want to send logs to Logentries or metrics to DataDog. Or write values to windows.location. And what happens if your database is X, Y or Z? -The list of effects is long and varied, with everyone needing to use a +The list of effects is long and varied, with everyone needing to use a different combination. So effect handling has to be extensible. You need a way to define diff --git a/docs/Solve-the-CPU-hog-problem.md b/docs/Solve-the-CPU-hog-problem.md index 8bef64ecb..82368ae9e 100644 --- a/docs/Solve-the-CPU-hog-problem.md +++ b/docs/Solve-the-CPU-hog-problem.md @@ -1,17 +1,4 @@ - - -## Table Of Contents -- [Solving The CPU Hog Problem](#solving-the-cpu-hog-problem) -- [The re-frame Solution](#the-re-frame-solution) -- [A Sketch](#a-sketch) - - [Why Does A Redispatch Work?](#why-does-a-redispatch-work) - - [Variations](#variations) - - [Cancel Button](#cancel-button) - - [Further Notes](#further-notes) -- [Forcing A One Off Render](#forcing-a-one-off-render) - - ## Solving The CPU Hog Problem @@ -234,3 +221,9 @@ You only need this technique when you: If you handle via multiple chunks you don't have to do this, because you are repeatedly handing back control to the browser/UI. Its just when you are going to tie up the CPU for a one, longish chunk. + + + + + + diff --git a/docs/The-re-frame-logo.md b/docs/The-re-frame-logo.md index 5081fb11f..ea2eec281 100644 --- a/docs/The-re-frame-logo.md +++ b/docs/The-re-frame-logo.md @@ -1,14 +1,3 @@ - - -## Table Of Contents - -- [The re-frame Logo](#the-re-frame-logo) - - [Who](#who) - - [Genesis Theories](#genesis-theories) - - [Assets Where?](#assets-where) - - - ## The re-frame Logo ![logo](/images/logo/re-frame_256w.png?raw=true) @@ -59,3 +48,9 @@ and "Why did you say I hit a horse?". Within this repo, look in `/images/logo/` + + + + + + From 3fc34786100bd2bf1a48d00dcd5833aa22fef5e0 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 22 Dec 2016 22:13:24 +1100 Subject: [PATCH 09/33] Add react-flip-move example to Resources --- docs/External-Resources.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/External-Resources.md b/docs/External-Resources.md index ff3f02afb..bc64df71b 100644 --- a/docs/External-Resources.md +++ b/docs/External-Resources.md @@ -22,7 +22,9 @@ Please add to this list by submitting a pull request. * [cookie-fx](https://github.com/SMX-LTD/re-frame-cookie-fx) - set and get cookies * [document-fx](https://github.com/SMX-LTD/re-frame-document-fx) - set and get on `js/document` attributes -### Tools +### Tools And Techniques + +* Animation using `react-flip-move`: http://www.upgradingdave.com/blog/posts/2016-12-17-permutation.html * [re-frisk](https://github.com/flexsurfer/re-frisk) - A library for visualizing re-frame data and events. From de8be2e69d0da8f9beb667ada7b4cf1bc39d2c08 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 22 Dec 2016 22:48:41 +1100 Subject: [PATCH 10/33] Improve FAQ entry --- docs/FAQs/Inspecting-app-db.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/FAQs/Inspecting-app-db.md b/docs/FAQs/Inspecting-app-db.md index d39ee557c..2c2c3bb06 100644 --- a/docs/FAQs/Inspecting-app-db.md +++ b/docs/FAQs/Inspecting-app-db.md @@ -16,7 +16,7 @@ If not, stop everything and immediately make that happen. Are you sure you need to? First, you seldom want to inspect all of `app-db`. -And, second, inspecting via figwheel will be clumsy. +And, second, inspecting via a REPL might be clumsy. Instead, you probably want to inspect a part of `app-db`. __And__ you probably want to inspect it directly in the GUI itself, not off in a REPL. @@ -52,14 +52,13 @@ You definitely have [clj-devtools](https://github.com/binaryage/cljs-devtools) i ### Other Inspection Tools +Another very strong tool is [re-Frisk](https://github.com/flexsurfer/re-frisk) which +provides a nice solution for navigating and inspecting your re-frame data structures. + @yogthos' [json-html library](https://github.com/yogthos/json-html) provides a slick presentation, at the expense of more screen real estate, and the need to include specific CSS. -There's also [Data Frisk](https://github.com/Odinodin/data-frisk-reagent) which -provides a very nice solution for navigating and inspecting any data structure. - - *** Up: [FAQ Index](README.md)       From 55919dedb0e58d16e75a4355e9bb139fa241b767 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Fri, 23 Dec 2016 20:52:18 +1100 Subject: [PATCH 11/33] Docs improvement --- docs/CodeWalkthrough.md | 3 +- docs/SubscriptionFlow.md | 18 +- docs/WIP/scratch-pad.md | 409 --------------------------------------- 3 files changed, 9 insertions(+), 421 deletions(-) delete mode 100644 docs/WIP/scratch-pad.md diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index 9c9b3ef76..df1397828 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -110,8 +110,7 @@ Here are some other example events: ```clj [:admit-to-being-satoshi false] -[:set-spam-wanted false :continue-harassment-nevertheless-flag] -[:some-ns/on-GET-success response] +[:dressing/put-pants-on "velour flares" {:method :left-leg-first :belt false}] ``` The `kind` of event is always a keyword, and for non-trivial diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index 110a3e833..bfc589230 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -1,12 +1,7 @@ ## Flow Mechanics -This tutorial is advanced and can be skipped. It provides background. -It explains at the underlying reactive mechanism for dominoes 4-5-6. - - - -### Table Of Contents - +This tutorial can be skipped. It provides advanced, background information. +It explains Reagent's underlying reactive mechanism used in dominoes 4-5-6. ## On Flow @@ -33,8 +28,7 @@ Steve Grand ### How Flow Happens In Reagent To implement a reactive flow, Reagent provides a `ratom` and a `reaction`. -re-frame uses both of these -building blocks, so let's now make sure we understand them. +re-frame uses both of these building blocks, so let's now make sure we understand them. `ratoms` behave just like normal ClojureScript atoms. You can `swap!` and `reset!` them, `watch` them, etc. @@ -43,7 +37,8 @@ perspective, we'll tweak that paradigm slightly and **view a `ratom` as having a changes over time.** Seems like a subtle distinction, I know, but because of it, re-frame sees a `ratom` as a Signal. -A Signal is a value that changes over time. So it is a stream of values. +A Signal is a value that changes over time. So it is a stream of values. Each time a ratom gets +`reset!` that's a new value in the stream. The 2nd building block, `reaction`, acts a bit like a function. It's a macro which wraps some `computation` (a block of code) and returns a `ratom` holding the result of that `computation`. @@ -214,3 +209,6 @@ Up: [Index](README.md)       Next: [Basic App Structure](Basic-App-Structure.md)        + + + diff --git a/docs/WIP/scratch-pad.md b/docs/WIP/scratch-pad.md deleted file mode 100644 index b8ee05414..000000000 --- a/docs/WIP/scratch-pad.md +++ /dev/null @@ -1,409 +0,0 @@ - ----------------- - -## Between 1 and 2 - -There's a queue. - -When you `dispatch` an event, it is put into a FIFO queue to be processed "vey soon". - -It is important to the design of re-frame that event processing is async. - -On the end of the queue, is a `router` which (very soon) will: - - pick up events one after the other - - for each, it extracts `kind` of event (first element of the event vector) - - for each, it looks up the associated event handler and calls it - - -## Between 2 and 3 - -I lied above. - -I said the `router` called the event handler associated with an event. This is a -useful simplification, but we'll see in future tutorials that there's more going on. - -I'll wave my hands about now and give you a sense of the real story. - -Instead of there being a single handler function, there's actually a pipeline of functions which -we call an interceptor chain. The handler you write is inserted into the middle of this pipeline. - -This function pipeline manages three things: - - it prepares the `coeffect` for the event handler (the set of inputs required by the handler) - - it calls the event handler (Domino 2) - - it handles the `effects` produced by the event handler (Domino 3) - - -The router actually looks up the associated "interceptor chain", which happens to have the handler wrapped on the end. - -And then it processes the interceptor chain. Which is to say it calls a - - -There's - - calls the handler , looks at their first , looks at their -first element, and runs the associated - -Between 1 and 2 it is a queue & router, -between 2 and 3 it is an interceptor pipeline, and along the 3-4-5-6 domino axis there's a reactive signal graph. The right -tool for the job in each case, I'd argue. - -While interconnections are critical to how **re-frame works**, -you can happily **use re-frame** for a long time and be mostly ignorant of their details. - -Which is a good thing - back we go to happy brains focusing on the **parts**. - - ------ - - -XXX - -I'll be using [Reagent] at an intermediate level, so you will need to have done some -introductory Reagent tutorials before going on. Try: - - [The Introductory Tutorial](http://reagent-project.github.io/) or - - [this one](https://github.com/jonase/reagent-tutorial) or - - [Building Single Page Apps with Reagent](http://yogthos.net/posts/2014-07-15-Building-Single-Page-Apps-with-Reagent.html). - -## Implements Reactive Data Flows - -This document describes how re-frame implements -the reactive data flows in dominoes 4 and 5 (queries and views). - -It explains -the low level mechanics of the process which not something you -need to know initially. So, you can defer reading and understanding -this until later, if you wish. But you should at some point circle -back and grok it. It isn't hard at all. - - - - -## Flow - - - -## Reactive Programming - - - -We'll get to the meat in a second, I promise, but first one final, useful diversion ... - -Terminology in the FRP world seems to get people hot under the collar. Those who believe in continuous-time -semantics might object to me describing re-frame as having FRP-nature. They'd claim that it does something -different from pure FRP, which is true. - -But, these days, FRP seems to have become a -["big tent"](http://soft.vub.ac.be/Publications/2012/vub-soft-tr-12-13.pdf) -(a broad church?). -Broad enough perhaps that re-frame can be in the far, top, left paddock of the tent, via a series of -qualifications: re-frame has "discrete, dynamic, asynchronous, push FRP-ish-nature" without "glitch free" guarantees. -(Surprisingly, "glitch" has specific meaning in FRP). - -**If you are new to FRP, or reactive programming generally**, browse these resources before -going further (certainly read the first two): -- [Creative Explanation](http://paulstovell.com/blog/reactive-programming) -- [Reactive Programming Backgrounder](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) -- [presentation (video)](http://www.infoq.com/presentations/ClojureScript-Javelin) by Alan Dipert (co-author of Hoplon) -- [serious pants Elm thesis](https://www.seas.harvard.edu/sites/default/files/files/archived/Czaplicki.pdf) - - - - - - - - -### React etc. - -Okay, so we have some unidirectional, dynamic, async, discrete FRP-ish data flow happening here. - -Question: To which ocean does this river of data flow? Answer: The DOM ocean. - -The full picture: -``` -app-db --> components --> Hiccup --> Reagent --> VDOM --> React --> DOM -``` - -Best to imagine this process as a pipeline of 3 functions. Each -function takes data from the -previous step, and produces (derived!) data for the next step. In the next -diagram, the three functions are marked (f1, f2, f3). The unmarked nodes are derived data, -produced by one step, to be input to the following step. Hiccup, -VDOM and DOM are all various forms of HTML markup (in our world that's data). - -``` -app-db --> components --> Hiccup --> Reagent --> VDOM --> React --> DOM - f1 f2 f3 -``` - -In abstract ClojureScript syntax terms, you could squint and imagine the process as: - -```Clojure -(-> app-db - components ;; produces Hiccup - Reagent ;; produces VDOM (virtual DOM that React understands) - React ;; produces HTML (which magically and efficiently appears on the page). - Browser ;; produces pixels - Monitor) ;; produces photons? -``` - - -Via the interplay between `ratom` and `reaction`, changes to `app-db` stream into the pipeline, where it -undergoes successive transformations, until pixels colour the monitor you to see. - -Derived Data, flowing. Every step is acting like a pure function and turning data into new data. - -All well and good, and nice to know, but we don't have to bother ourselves with most of the pipeline. -We just write the `components` -part and Reagent/React will look after the rest. So back we go to that part of the picture ... - - -## Subscribe - - - -`components` (view layer) need to query aspects of `app-db` (data layer). - -But how? - -Let's pause to consider **our dream solution** for this part of the flow. `components` would: - * obtain data from `app-db` (their job is to turn this data into hiccup). - * obtain this data via a (possibly parameterised) query over `app-db`. Think database kind of query. - * automatically recompute their hiccup output, as the data returned by the query changes, over time - * use declarative queries. Components should know as little as possible about the structure of `app-db`. SQL? Datalog? - -re-frame's `subscriptions` are an attempt to live this dream. As you'll see, they fall short on the declarative -query part, but they comfortably meet the other requirements. - -As a re-frame app developer, your job will be to write and register one or more -"subscription handlers" - functions that do a named query. - -Your subscription functions must return a value that changes over time (a Signal). I.e. they'll -be returning a reaction or, at least, the `ratom` produced by a `reaction`. - -Rules: - - `components` never source data directly from `app-db`, and instead, they use a subscription. - - subscriptions are only ever used by components (they are never used in, say, event handlers). - -Here's a component using a subscription: - -```Clojure -(defn greet ;; outer, setup function, called once - [] - (let [name-ratom (subscribe [:name-query])] ;; <---- subscribing happens here - (fn [] ;; the inner, render function, potentially called many times. - [:div "Hello" @name-ratom]))) -``` - -First, note this is a [Form-2](https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components#form-2--a-function-returning-a-function) -`component` ([there are 3 forms](https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components)). - -Previously in this document, we've used the simplest, `Form-1` components (no setup was required, just render). -With `Form-2` components, there's a function returning a function: -- the returned function is the render function. Behind the scenes, Reagent will wrap this render function - in a `reaction` to make it produce new Hiccup when its input Signals change. In our example above, that - means it will rerun every time `name-ratom` changes. -- the outer function is a setup function, called once for each instance of the component. Notice the use of - 'subscribe' with the parameter `:name-query`. That creates a Signal through which new values are supplied - over time; each new value causing the returned function (the actual renderer) to be run. - ->It is important to distinguish between a new instance of the component versus the same instance of a component reacting to a new value. Simplistically, a new component is returned for every unique value the setup function (i.e. the outer function) is called with. This allows subscriptions based on initialisation values to be created, for example: -``` Clojure - (defn my-cmp [row-id] - (let [row-state (subscribe [row-id])] - (fn [row-id] - [:div (str "Row: " row-id " is " @row-state)]))) -``` -In this example, `[my-cmp 1][my-cmp 2]` will create two instances of `my-cmp`. Each instance will re-render when its internal `row-state` signal changes. - -`subscribe` is always called like this: - -```Clojure - (subscribe [query-id some optional query parameters]) -``` - -There is only one (global) `subscribe` function and it takes one parameter, assumed to be a vector. - -The first element in the vector (shown as `query-id` above) identifies/names the query and the other elements are optional -query parameters. With a traditional database a query might be: - -``` -select * from customers where name="blah" -``` - -In re-frame, that would be done as follows: - `(subscribe [:customer-query "blah"])` -which would return a `ratom` holding the customer state (a value which might change over time!). - -So let's now look at how to write and register the subscription handler for `:customer-query` - -```Clojure -(defn customer-query ;; a query over 'app-db' which returns a customer - [db, [sid cid]] ;; query fns are given 'app-db', plus vector given to subscribe - (assert (= sid :customer-query)) ;; subscription id was the first element in the vector - (reaction (get-in @db [:path :to :a :map cid]))) ;; re-runs each time db changes - -;; register our query handler -(register-sub - :customer-query ;; the id (the name of the query) - customer-query) ;; the function which will perform the query -``` - -Notice how the handler is registered to handle `:customer-query` subscriptions. - -**Rules and Notes**: - - you'll be writing one or more handlers, and you will need to register each one. - - handlers are functions which take two parameters: the db atom, and the vector given to subscribe. - - `components` tend to be organised into a hierarchy, often with data flowing from parent to child via -parameters. So not every component needs a subscription. Very often the values passed in from a parent component -are sufficient. - - subscriptions can only be used in `Form-2` components and the subscription must be in the outer setup -function and not in the inner render function. So the following is **wrong** (compare to the correct version above) - -```Clojure -(defn greet ;; a Form-1 component - no inner render function - [] - (let [name-ratom (subscribe [:name-query])] ;; Eek! subscription in renderer - [:div "Hello" @name-ratom])) -``` - -Why is this wrong? Well, this component would be re-rendered every time `app-db` changed, even if the value -in `name-ratom` (the result of the query) stayed the same. If you were to use a `Form-2` component instead, and put the -subscription in the outer functions, then there'll be no re-render unless the value queried (i.e. `name-ratom`) changed. - - -## The Signal Graph - -Let's sketch out the situation described above ... - -`app-db` would be a bit like this (`items` is a vector of maps): -```Clojure -(def L [{:name "a" :val 23 :flag "y"} - {:name "b" :val 81 :flag "n"} - {:name "c" :val 23 :flag "y"}]) - -(def app-db (reagent/atom {:items L - :sort-by :name})) ;; sorted by the :name attribute -``` - -The subscription-handler might be written: - -```Clojure -(register-sub - :sorted-items ;; the query id (the name of the query) - (fn [db [_]] ;; the handler for the subscription - (reaction - (let [items (get-in @db [:items]) ;; extract items from db - sort-attr (get-in @db [:sort-by])] ;; extract sort key from db - (sort-by sort-attr items))))) ;; return them sorted -``` - - -Subscription handlers are given two parameters: - - 1. `app-db` - that's a reagent/atom which holds ALL the app's state. This is the "database" - on which we perform the "query". - 2. the vector originally supplied to `subscribe`. In our case, we ignore it. - -In the example above, notice that the `reaction` depends on the input Signal: `db`. -If `db` changes, the query is re-run. - -In a component, we could use this query via `subscribe`: - -```Clojure -(defn items-list ;; Form-2 component - outer, setup function, called once - [] - (let [items (subscribe [:sorted-items]) ;; <-- subscribe called with name - num (reaction (count @items)) ;; Woh! a reaction based on the subscription - top-20 (reaction (take 20 @items))] ;; Another dependent reaction - (fn [] - [:div - (str "there's " @num " of these suckers. Here's top 20") ;; rookie mistake to leave off the @ - (into [:div ] (map item-render @top-20))]))) ;; item-render is another component, not shown -``` - -There's a bit going on in that `let`, most of it tortuously contrived, just so I can show off chained -reactions. Okay, okay, all I wanted really was an excuse to use the phrase "chained reactions". - -The calculation of `num` is done by a `reaction` which has `items` as an input Signal. And, -as we saw, `items` is itself a reaction over two other signals (one of them the `app-db`). - -So this is a Signal Graph. Data is flowing through computation into renderer, which produce Hiccup, etc. - -## A More Efficient Signal Graph - -But there is a small problem. The approach above might get inefficient, if `:items` gets long. - -Every time `app-db` changes, the `:sorted-items` query is -going to be re-run and it's going to re-sort `:items`. But `:items` might not have changed. Some other -part of `app-db` may have changed. - -We don't want to perform this computationally expensive re-sort -each time something unrelated in `app-db` changes. - -Luckily, we can easily fix that up by tweaking our subscription function so -that it chains `reactions`: - -```Clojure -(register-sub - :sorted-items ;; the query id - (fn [db [_]] - (let [items (reaction (get-in @db [:some :path :to :items]))] ;; reaction #1 - sort-attr (reaction (get-in @db [:sort-by]))] ;; reaction #2 - (reaction (sort-by @sort-attr @items))))) ;; reaction #3 -``` - -The original version had only one `reaction` which would be re-run completely each time `app-db` changed. -This new version, has chained reactions. -The 1st and 2nd reactions just extract from `db`. They will run each time `app-db` changes. -But they are cheap. The 3rd one does the expensive -computation using the result from the first two. - -That 3rd, expensive reaction will be re-run when either one of its two input Signals change, right? Not quite. -`reaction` will only re-run the computation when one of the inputs has **changed in value**. - -`reaction` compares the old input Signal value with the new Signal value using `identical?`. Because we're -using immutable data structures -(thank you ClojureScript), `reaction` can perform near instant checks for change on even -deeply nested and complex -input Signals. And `reaction` will then stop unneeded propagation of `identical?` values through the -Signal graph. - -In the example above, reaction #3 won't re-run until `:items` or `:sort-by` are different -(do not test `identical?` -to their previous value), even though `app-db` itself has changed (presumably somewhere else). - -Hideously contrived example, but I hope you get the idea. It is all screamingly efficient. - -Summary: - - you can chain reactions. - - a reaction will only be re-run when its input Signals test not `identical?` to previous value. - - As a result, unnecessary Signal propagation is eliminated using highly efficient checks, - even for large, deep nested data structures. - - - - - -Back to the more pragmatic world ... - - - -[SPAs]:http://en.wikipedia.org/wiki/Single-page_application -[SPA]:http://en.wikipedia.org/wiki/Single-page_application -[Reagent]:http://reagent-project.github.io/ -[Dan Holmsand]:https://twitter.com/holmsand -[Flux]:http://facebook.github.io/flux/docs/overview.html#content -[Hiccup]:https://github.com/weavejester/hiccup -[FRP]:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 -[Elm]:http://elm-lang.org/ -[OM]:https://github.com/swannodette/om -[Prismatic Schema]:https://github.com/Prismatic/schema -[Hoplon]:http://hoplon.io/ -[Pedestal App]:https://github.com/pedestal/pedestal-app - - - - -## Table Of Contents - - From fd586188a3fde97573a3b76626328918f54662ba Mon Sep 17 00:00:00 2001 From: Illia Zub Date: Fri, 23 Dec 2016 12:13:29 +0200 Subject: [PATCH 12/33] Fix links to DataScript database --- docs/ApplicationState.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ApplicationState.md b/docs/ApplicationState.md index 4dc5f038e..2f4debdf8 100644 --- a/docs/ApplicationState.md +++ b/docs/ApplicationState.md @@ -47,8 +47,8 @@ Further Notes: you don't need to declare one yourself (see the [the first FAQ](FAQs/Inspecting-app-db.md) if you want to inspect the value it holds). 4. `app-db` doesn't actually have to be a `ratom` containing a map. It could, for example, - be a [datascript](https://github.com/tonsky/datascript database). In fact, any database which - can signal you when it changes would do. We'd love! to be using [datascript](https://github.com/tonsky/datascript database) - so damn cool - + be a [datascript database](https://github.com/tonsky/datascript). In fact, any database which + can signal you when it changes would do. We'd love! to be using [datascript database](https://github.com/tonsky/datascript) - so damn cool - but we had too much data in our apps. If you were to use it, you'd have to tweak re-frame a bit and use [Posh](https://github.com/mpdairy/posh). From 9f1f54b1244ee3aaef7ec6d35f855ce310bbd76e Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Sun, 25 Dec 2016 06:02:47 +1100 Subject: [PATCH 13/33] Clean up External Resources for Effects --- docs/Effects.md | 10 +-------- docs/External-Resources.md | 44 +++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/docs/Effects.md b/docs/Effects.md index 1a9ade204..d9440c88d 100644 --- a/docs/Effects.md +++ b/docs/Effects.md @@ -347,16 +347,8 @@ usage: ### External Effects -- https://github.com/Day8/re-frame-http-fx (GETs and POSTs) -- https://github.com/Day8/re-frame-forward-events-fx (slightly exotic) -- https://github.com/Day8/re-frame-async-flow-fx (more complicated) -- https://github.com/micmarsh/re-frame-youtube-fx (YouTube iframe API wrapper) -- https://github.com/madvas/re-frame-web3-fx (Ethereum Web3 API) -- https://github.com/madvas/re-frame-google-analytics-fx (Google Analytics API) +Please see the [External-Resources document](External-Resources.md) for a list of 3rd part Effect Handlers. -Create a PR to include yours in this list. - -XXX maybe put this list into the Wiki, so editable by all. *** diff --git a/docs/External-Resources.md b/docs/External-Resources.md index bc64df71b..6a63c4c85 100644 --- a/docs/External-Resources.md +++ b/docs/External-Resources.md @@ -5,7 +5,7 @@ Please add to this list by submitting a pull request. ### Templates -* [re-frame-template](https://github.com/Day8/re-frame-template) - Generates just the client side SPA +* [re-frame-template](https://github.com/Day8/re-frame-template) - Generates the client side SPA * [Luminus](http://www.luminusweb.net) - Generates SPA plus server side. @@ -15,20 +15,6 @@ Please add to this list by submitting a pull request. * [Celibidache](https://github.com/velveteer/celibidache/) - An opinionated starter for re-frame applications using Boot. Based on re-frame `0.7.0` -### Effect and CoEffect Handlers - -* [async-flow-fx](https://github.com/Day8/re-frame-async-flow-fx) - manage a boot process dominated by async -* [http-fx](https://github.com/Day8/re-frame-http-fx) - performing Ajax tasks (via cljs-ajax) -* [cookie-fx](https://github.com/SMX-LTD/re-frame-cookie-fx) - set and get cookies -* [document-fx](https://github.com/SMX-LTD/re-frame-document-fx) - set and get on `js/document` attributes - -### Tools And Techniques - -* Animation using `react-flip-move`: http://www.upgradingdave.com/blog/posts/2016-12-17-permutation.html - -* [re-frisk](https://github.com/flexsurfer/re-frisk) - A library for visualizing re-frame data and events. - -* [re-thread](https://github.com/yetanalytics/re-thread) - A library for running re-frame applications in Web Workers. ### Examples and Applications Using re-frame @@ -51,10 +37,24 @@ Please add to this list by submitting a pull request. * [Angular Phonecat tutorial in re-frame](http://dhruvp.github.io/2015/03/07/re-frame/) - A detailed step-by-step tutorial that ports the Angular Phonecat tutorial to re-frame. Based on re-frame `0.2.0` -### Libraries -* [re-frame-datatable](https://github.com/kishanov/re-frame-datatable) - DataTable UI component built for use with re-frame. +### Effect and CoEffect Handlers + +* [async-flow-fx](https://github.com/Day8/re-frame-async-flow-fx) - manage a boot process dominated by async +* [http-fx](https://github.com/Day8/re-frame-http-fx) - performing Ajax tasks (via cljs-ajax) +* [re-frame-forward-events-fx](https://github.com/Day8/re-frame-forward-events-fx) - slightly exotic +* [cookie-fx](https://github.com/SMX-LTD/re-frame-cookie-fx) - set and get cookies +* [document-fx](https://github.com/SMX-LTD/re-frame-document-fx) - set and get on `js/document` attributes +* [re-frame-youtube-fx](https://github.com/micmarsh/re-frame-youtube-fx) - YouTube iframe API wrapper +* [re-frame-web3-fx](https://github.com/madvas/re-frame-web3-fx) - Ethereum Web3 API +* [re-frame-google-analytics-fx](https://github.com/madvas/re-frame-google-analytics-fx) - Google Analytics API + +### Tools And Techniques +* Animation using `react-flip-move`: http://www.upgradingdave.com/blog/posts/2016-12-17-permutation.html +* [re-frisk](https://github.com/flexsurfer/re-frisk) - A library for visualizing re-frame data and events. +* [re-thread](https://github.com/yetanalytics/re-thread) - A library for running re-frame applications in Web Workers. +* [re-frame-datatable](https://github.com/kishanov/re-frame-datatable) - DataTable UI component built for use with re-frame. * [Stately: State Machines](https://github.com/nodename/stately) also https://www.youtube.com/watch?v=klqorRUPluw ### Videos @@ -66,16 +66,16 @@ Please add to this list by submitting a pull request. ### Server Side Rendering * [Prerenderer](https://github.com/pupeno/prerenderer) - Server pre-rendering library using NodeJS that works with re-frame `0.6.0` (later versions untested) - * [Rationale Part 1](https://carouselapps.com/2015/09/14/isomorphic-clojurescriptjavascript-for-pre-rendering-single-page-applications-part-2/) - * [Rationale Part 2](https://carouselapps.com/2015/09/14/isomorphic-clojurescriptjavascript-for-pre-rendering-single-page-applications-part-2/) - * [Rationale Part 3](https://pupeno.com/2015/10/02/isomorphic-javascript-with-clojurescript-for-pre-rendering-single-page-applications-part-3/) - * [Release Announcement](https://pupeno.com/2015/12/13/prerenderer-0-2-0-released/) + Rationale [Part 1](https://carouselapps.com/2015/09/14/isomorphic-clojurescriptjavascript-for-pre-rendering-single-page-applications-part-2/) + [Part 2](https://carouselapps.com/2015/09/14/isomorphic-clojurescriptjavascript-for-pre-rendering-single-page-applications-part-2/) + [Part 3](https://pupeno.com/2015/10/02/isomorphic-javascript-with-clojurescript-for-pre-rendering-single-page-applications-part-3/) + [Release Announcement](https://pupeno.com/2015/12/13/prerenderer-0-2-0-released/) * [Server Side Rendering with re-frame](http://davidtanzer.net/server_side_rendering_with_re_frame) - Blog post on rendering re-frame views with Clojure. * [Rendering Reagent on the Server Using Hiccup](http://yogthos.net/posts/2015-11-24-Serverside-Reagent.html)- Blog post on rendering Reagent with Clojure. + - From dc63a4f99d0bec7d2e31bd31273957ee3d9dbccd Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Sun, 25 Dec 2016 07:13:10 +1100 Subject: [PATCH 14/33] More work on External Resouces --- README.md | 8 ++++---- docs/External-Resources.md | 6 ++++-- docs/SubscriptionFlow.md | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e3c19a507..3d1457d5b 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ change, but sometimes the outside world must also be effected ### 3rd Domino - Effect Handling -The descriptions of `effects` are realised (actioned). This is where mutations happens. +The descriptions of `effects` are realised (actioned). Now, to a functional programmer, `effects` are scary in a [xenomorph kind of way](https://www.google.com.au/search?q=xenomorph). @@ -143,17 +143,17 @@ never achieving anything. So re-frame embraces the protagonist nature of `effects` - the entire, unruly zoo of them - but it does so in a largely hidden way, and in a manner which is debuggable, auditable, mockable and pluggable. -### A Pivot Point +### We're At A Pivot Point The world just changed and, very often, one particular part of it: the **application state**. re-frame's `app state` is held in one place - think of it like you -would an in-memory, central database for the app (more details later). +would an in-memory, central database for the app (details later). When domino 3 changes this `app state`, it triggers the next part of the cascade involving dominoes 4-5-6. -### There's a formula +### There's a Formula The 4-5-6 domino cascade implements the formula made famous by Facebook's ground-breaking React library: `v = f(s)` diff --git a/docs/External-Resources.md b/docs/External-Resources.md index 6a63c4c85..bc2197358 100644 --- a/docs/External-Resources.md +++ b/docs/External-Resources.md @@ -49,13 +49,15 @@ Please add to this list by submitting a pull request. * [re-frame-web3-fx](https://github.com/madvas/re-frame-web3-fx) - Ethereum Web3 API * [re-frame-google-analytics-fx](https://github.com/madvas/re-frame-google-analytics-fx) - Google Analytics API -### Tools And Techniques +### Tools, Techniques & Libraries -* Animation using `react-flip-move`: http://www.upgradingdave.com/blog/posts/2016-12-17-permutation.html +* [re-frame-undo](https://github.com/Day8/re-frame-undo) - An undo library for re-frame +* Animation using `react-flip-move` - http://www.upgradingdave.com/blog/posts/2016-12-17-permutation.html * [re-frisk](https://github.com/flexsurfer/re-frisk) - A library for visualizing re-frame data and events. * [re-thread](https://github.com/yetanalytics/re-thread) - A library for running re-frame applications in Web Workers. * [re-frame-datatable](https://github.com/kishanov/re-frame-datatable) - DataTable UI component built for use with re-frame. * [Stately: State Machines](https://github.com/nodename/stately) also https://www.youtube.com/watch?v=klqorRUPluw +* [re-frame-test](https://github.com/Day8/re-frame-test) - Integration Testing (not documented) ### Videos diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index bfc589230..4b4ec54bb 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -1,7 +1,7 @@ ## Flow Mechanics -This tutorial can be skipped. It provides advanced, background information. -It explains Reagent's underlying reactive mechanism used in dominoes 4-5-6. +If you are in a hurry, this tutorial can be skipped. It provides advanced, background information. +It explains the underlying reactive mechanism used in dominoes 4-5-6. ## On Flow From 2b1750159e77db157393cbfaf50790093ba0ff3a Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 06:51:00 +1100 Subject: [PATCH 15/33] Improve docs on reg-sub-raw --- docs/Subscribing-To-External-Data.md | 46 ++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/Subscribing-To-External-Data.md b/docs/Subscribing-To-External-Data.md index 3095924ca..1c2b41e94 100644 --- a/docs/Subscribing-To-External-Data.md +++ b/docs/Subscribing-To-External-Data.md @@ -131,12 +131,12 @@ Enough fluffing about with words, here's a code sketch for our subscription hand ```clj (re-frame/reg-sub-raw :items - (fn [db [_ type]] + (fn [app-db [_ type]] (let [query-token (issue-items-query! type :on-success #(re-frame/dispatch [:write-to [:some :path]]))] (reagent/make-reaction - (fn [] (get-in @db [:some :path] [])) + (fn [] (get-in @app-db [:some :path] [])) :on-dispose #(do (terminate-items-query! query-token) (re-frame/dispatch [:cleanup [:some :path]])))))) ``` @@ -164,6 +164,48 @@ A few things to notice: 4. We use the `on-dispose` callback on this reaction to do any cleanup work when the subscription is no longer needed. Clean up `app-db`? Clean up the database connection? +### A Brief Introduction To reg-sub-raw + +It provides a low level way to register a subscription handler - so the intent is similar to `reg-sub`, +but the semantics are different. + +Usage is fairly re-frame standard: +```clj +(reg-sub-raw + :query-id ;; later use (subscribe [:query-id]) + some-fn) +``` + +Here's an example `some-fn`: +```clj +(defn some-fn + [app-db event] ;; app-db is not a value, it is a reagent/atom + (reaction (get-in @app-db [:some :path))) ;; returns a reaction +``` +Notice: + 1. `app-db` is the first argument and it is not a value, it is a reagent/atom + 2. it must return a `reaction` + 3. Within that `reaction` `app-db` is deref-ed (see use of `@`) + +Each time `app-db` changes, this reaction will rerun. `app-db` is an input signal to the reaction. +To understand `reaction`, [please read the docs here](SubscriptionFlow.md) + +There is no arity of `reg-sub-raw` which allows you to provide an input signals function, so it is different to `reg-sub`. +The first argument to `some-fn` is always `app-db` and, to use other input signals, you +must use a `subscription` within the `reaction` itself. For example: +```clj +(defn some-fn + [app-db event] + (reaction + (let [a-path-element @(subscribe [:get-path-part])] ;; <-- subscribe used here + get-in @app-db [:some a-path-element]))) +``` +So now there are two input signals: `app-db` and `(subscribe [:get-path-part])`. In some cases you might not even +use `app-db` and use only `subscribes` as inputs signals. + +Of course, above in our `:items` handler, we are not using `reaction`, and instead we are using `make-reaction` +so we can attach an `:on-dispose` handler, but the process is the same. + ### Any Good? It turns out that this is a surprisingly flexible and clean approach. And pretty damn obvious once From 51a2e7f5d8bd7d4a2fbbb3170e89bf2e6186bb58 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 08:41:15 +1100 Subject: [PATCH 16/33] Move docs on reg-sub-raw --- docs/Subscribing-To-External-Data.md | 45 ++-------------------------- docs/SubscriptionFlow.md | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/docs/Subscribing-To-External-Data.md b/docs/Subscribing-To-External-Data.md index 1c2b41e94..41b923da0 100644 --- a/docs/Subscribing-To-External-Data.md +++ b/docs/Subscribing-To-External-Data.md @@ -144,8 +144,8 @@ Enough fluffing about with words, here's a code sketch for our subscription hand A few things to notice: 1. We are using the low level `reg-sub-raw` registration for our handler (and not `reg-sub`). - This gives us some low level control. `db` will be an atom. We must return a - `reaction` (signal). + This gives us some low level control. `app-db` will be an atom. We must return a + `reaction` (signal). [See the `reg-sub-raw` docs at the end of this tutorial](SubscriptionFlow.md) 2. You have to write `issue-items-query!`. Are you making a Restful GET? Are you writing JSON packets down a websocket? The query has to be made. @@ -164,47 +164,6 @@ A few things to notice: 4. We use the `on-dispose` callback on this reaction to do any cleanup work when the subscription is no longer needed. Clean up `app-db`? Clean up the database connection? -### A Brief Introduction To reg-sub-raw - -It provides a low level way to register a subscription handler - so the intent is similar to `reg-sub`, -but the semantics are different. - -Usage is fairly re-frame standard: -```clj -(reg-sub-raw - :query-id ;; later use (subscribe [:query-id]) - some-fn) -``` - -Here's an example `some-fn`: -```clj -(defn some-fn - [app-db event] ;; app-db is not a value, it is a reagent/atom - (reaction (get-in @app-db [:some :path))) ;; returns a reaction -``` -Notice: - 1. `app-db` is the first argument and it is not a value, it is a reagent/atom - 2. it must return a `reaction` - 3. Within that `reaction` `app-db` is deref-ed (see use of `@`) - -Each time `app-db` changes, this reaction will rerun. `app-db` is an input signal to the reaction. -To understand `reaction`, [please read the docs here](SubscriptionFlow.md) - -There is no arity of `reg-sub-raw` which allows you to provide an input signals function, so it is different to `reg-sub`. -The first argument to `some-fn` is always `app-db` and, to use other input signals, you -must use a `subscription` within the `reaction` itself. For example: -```clj -(defn some-fn - [app-db event] - (reaction - (let [a-path-element @(subscribe [:get-path-part])] ;; <-- subscribe used here - get-in @app-db [:some a-path-element]))) -``` -So now there are two input signals: `app-db` and `(subscribe [:get-path-part])`. In some cases you might not even -use `app-db` and use only `subscribes` as inputs signals. - -Of course, above in our `:items` handler, we are not using `reaction`, and instead we are using `make-reaction` -so we can attach an `:on-dispose` handler, but the process is the same. ### Any Good? diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index 4b4ec54bb..84486b6b3 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -202,6 +202,51 @@ ratom-nature, so we'll happily continue believing it is a `ratom` and no harm wi On with the rest of my lies and distortions... +### reg-sub-raw + +It provides a low level way to register a subscription handler - so the intent is similar to `reg-sub`. + +Use is re-frame standard: +```clj +(reg-sub-raw + :query-id ;; later use (subscribe [:query-id]) + some-fn) ;; this function provides the reactive stream +``` + +The interesting bit is how `some-fn` is written. Here's an example: +```clj +(defn some-fn + [app-db event] ;; app-db is not a value, it is a reagent/atom + (reaction (get-in @app-db [:some :path))) ;; returns a reaction +``` +Notice: + 1. `app-db` is the first argument and it is not a value, it is a reagent/atom (different to reg-sub!) + 2. it returns a `reaction` which does a computation, not a value (different to reg-sub!) + 3. Within that `reaction` `app-db` is deref-ed (see use of `@`) + +As a result of point 3, each time `app-db` changes, the `reaction` will rerun. `app-db` is an input signal to that `reaction`. + +Unlike `reg-sub`, there is no 3-arity version of `reg-sub-raw`, so you con't provide an input signals function. +Instead, you just use a `subscribe` within the `reaction` itself. For example: +```clj +(defn some-fn + [app-db event] + (reaction + (let [a-path-element @(subscribe [:get-path-part])] ;; <-- subscribe used here + get-in @app-db [:some a-path-element]))) +``` +So now this `reaction` has two input signals: `app-db` and `(subscribe [:get-path-part])`. If either changes, +the `reaction` will rerun. + +In some cases, the `reaction` might not even +use `app-db` and use only `subscribe` to provide input signals. + +Remember to deref any use of `app-db` and `subscribe`. It is a rookie mistake to forget. I do it all the time. + +Instead of returning a `reaction` (a macro) you can use `reagent/make-reaction` (a function) which gives you the additional +ability to attach an `:on-dispose` handler to a reaction, allowing you to do comething when the subscription is no longer needed. +[See an example of using `:on-dispose` here](Subscribing-To-External-Data.md) + *** Previous: [Correcting a wrong](SubscriptionsCleanup.md)       From 6ae5d8ec4ff9d9f5686d0cf5ddfbdecfb7831c74 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 09:05:25 +1100 Subject: [PATCH 17/33] Docs typos --- docs/SubscriptionFlow.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index 84486b6b3..c58c453ce 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -204,11 +204,11 @@ On with the rest of my lies and distortions... ### reg-sub-raw -It provides a low level way to register a subscription handler - so the intent is similar to `reg-sub`. +Provides a low level way to register a subscription handler - so the intent is similar to `reg-sub`. Use is re-frame standard: ```clj -(reg-sub-raw +(re-frame.core/reg-sub-raw ;; it is part of the API :query-id ;; later use (subscribe [:query-id]) some-fn) ;; this function provides the reactive stream ``` @@ -216,18 +216,18 @@ Use is re-frame standard: The interesting bit is how `some-fn` is written. Here's an example: ```clj (defn some-fn - [app-db event] ;; app-db is not a value, it is a reagent/atom - (reaction (get-in @app-db [:some :path))) ;; returns a reaction + [app-db event] ;; app-db is not a value, it is a reagent/atom + (reaction (get-in @app-db [:some :path]))) ;; returns a reaction ``` Notice: - 1. `app-db` is the first argument and it is not a value, it is a reagent/atom (different to reg-sub!) - 2. it returns a `reaction` which does a computation, not a value (different to reg-sub!) + 1. `app-db` is the first argument and it is NOT a value, it is a reagent/atom (different to `reg-sub`!) + 2. it returns a `reaction` which does a computation, not a value (different to `reg-sub`!) 3. Within that `reaction` `app-db` is deref-ed (see use of `@`) As a result of point 3, each time `app-db` changes, the `reaction` will rerun. `app-db` is an input signal to that `reaction`. -Unlike `reg-sub`, there is no 3-arity version of `reg-sub-raw`, so you con't provide an input signals function. -Instead, you just use a `subscribe` within the `reaction` itself. For example: +Unlike `reg-sub`, there is no 3-arity version of `reg-sub-raw`, so there's no way for you to provide an input signals function. +Instead, even simplier, you can use any `subscribe` you want within the `reaction` itself. For example: ```clj (defn some-fn [app-db event] @@ -238,13 +238,14 @@ Instead, you just use a `subscribe` within the `reaction` itself. For example: So now this `reaction` has two input signals: `app-db` and `(subscribe [:get-path-part])`. If either changes, the `reaction` will rerun. -In some cases, the `reaction` might not even -use `app-db` and use only `subscribe` to provide input signals. +In some cases, the returned `reaction` might not even +use `app-db` and, instead, it might only use `subscribe` to provide input signals. In that case, the +registered subscription would belong to "Level 3" of the signal graph (discussed in earlier tutorials). -Remember to deref any use of `app-db` and `subscribe`. It is a rookie mistake to forget. I do it all the time. +Remember to deref any use of `app-db` and `subscribe`. It is a rookie mistake to forget. I do it regularly. -Instead of returning a `reaction` (a macro) you can use `reagent/make-reaction` (a function) which gives you the additional -ability to attach an `:on-dispose` handler to a reaction, allowing you to do comething when the subscription is no longer needed. +Instead of returning a `reaction` (a macro), you can use `reagent/make-reaction` (a utility function) which gives you the additional +ability to attach an `:on-dispose` handler to the returned reaction, allowing you to do cleanup work when the subscription is no longer needed. [See an example of using `:on-dispose` here](Subscribing-To-External-Data.md) *** From bd58f7d1a7fe10a41a6f241133409c293005ca63 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 09:09:19 +1100 Subject: [PATCH 18/33] Docs clarity --- docs/SubscriptionFlow.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index c58c453ce..b98e14509 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -244,7 +244,7 @@ registered subscription would belong to "Level 3" of the signal graph (discussed Remember to deref any use of `app-db` and `subscribe`. It is a rookie mistake to forget. I do it regularly. -Instead of returning a `reaction` (a macro), you can use `reagent/make-reaction` (a utility function) which gives you the additional +Instead of using `reaction` (a macro), you can use `reagent/make-reaction` (a utility function) which gives you the additional ability to attach an `:on-dispose` handler to the returned reaction, allowing you to do cleanup work when the subscription is no longer needed. [See an example of using `:on-dispose` here](Subscribing-To-External-Data.md) From 649d9d9ef147ba6a9804cbb5fc3c38c1d8a40623 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 09:22:51 +1100 Subject: [PATCH 19/33] Add example use of reg-sub-raw --- docs/SubscriptionFlow.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index b98e14509..857013aff 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -248,6 +248,39 @@ Instead of using `reaction` (a macro), you can use `reagent/make-reaction` (a ut ability to attach an `:on-dispose` handler to the returned reaction, allowing you to do cleanup work when the subscription is no longer needed. [See an example of using `:on-dispose` here](Subscribing-To-External-Data.md) +### Example reg-sub-raw + +The following use of `reg-sub` can be found in [the todomvc example](): +```clj +(reg-sub + :visible-todos + (fn [query-v _] ;; returns a vector of two signals. + [(subscribe [:todos]) + (subscribe [:showing])]) + + (fn [[todos showing] _] ;; that 1st parameter is a 2-vector of values + (let [filter-fn (case showing + :active (complement :done) + :done :done + :all identity)] + (filter filter-fn todos)))) +``` + +we could rewrite that using `reg-sub-raw` like this: +```clj +(reg-sub-raw + :visible-todos + (fn [app-db event] ;; app-db not used, shown for clarity + (rection + (let [todos @(subscribe [:todos]) + showing @(subscribe [:showing]) + filter-fn (case showing + :active (complement :done) + :done :done + :all identity)] + (filter filter-fn todos)))) +``` + *** Previous: [Correcting a wrong](SubscriptionsCleanup.md)       From 3657f0fd9c9fd5d1ff64243cd0720107508a96f9 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 09:31:22 +1100 Subject: [PATCH 20/33] More reg-sub-raw --- docs/SubscriptionFlow.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index 857013aff..e8a6575ac 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -250,15 +250,18 @@ ability to attach an `:on-dispose` handler to the returned reaction, allowing yo ### Example reg-sub-raw -The following use of `reg-sub` can be found in [the todomvc example](): +The following use of `reg-sub` can be found in [the todomvc example](https://github.com/Day8/re-frame/blob/develop/examples/todomvc/src/todomvc/subs.cljs): ```clj (reg-sub :visible-todos - (fn [query-v _] ;; returns a vector of two signals. + + ;; signal function - returns a vector of two input signals + (fn [query-v _] [(subscribe [:todos]) (subscribe [:showing])]) - (fn [[todos showing] _] ;; that 1st parameter is a 2-vector of values + ;; the computation function - 1st arg is a 2-vector of values + (fn [[todos showing] _] (let [filter-fn (case showing :active (complement :done) :done :done @@ -266,14 +269,14 @@ The following use of `reg-sub` can be found in [the todomvc example](): (filter filter-fn todos)))) ``` -we could rewrite that using `reg-sub-raw` like this: +we could rewrite this use of `reg-sub` using `reg-sub-raw` like this: ```clj (reg-sub-raw :visible-todos - (fn [app-db event] ;; app-db not used, shown for clarity - (rection - (let [todos @(subscribe [:todos]) - showing @(subscribe [:showing]) + (fn [app-db event] ;; app-db not used, name shown for clarity + (reaction ;; wrap the computation in a reaction + (let [todos @(subscribe [:todos]) ;; input signal #1 + showing @(subscribe [:showing]) ;; input signal #2 filter-fn (case showing :active (complement :done) :done :done @@ -281,6 +284,10 @@ we could rewrite that using `reg-sub-raw` like this: (filter filter-fn todos)))) ``` +Any other part of the app, which needed to do `(subscribe [:visible-todos])` need never know which of the two variations above was used. Same result. + + + *** Previous: [Correcting a wrong](SubscriptionsCleanup.md)       From 209470e76130eb234acac46b9bedfc51bbeec0ab Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 16:13:02 +1100 Subject: [PATCH 21/33] Correct the `:id` given to `on-change` interceptor (ie. fix cut and paste typo) --- src/re_frame/std_interceptors.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/re_frame/std_interceptors.cljc b/src/re_frame/std_interceptors.cljc index 993b1e4f2..6fd8c7f93 100644 --- a/src/re_frame/std_interceptors.cljc +++ b/src/re_frame/std_interceptors.cljc @@ -270,7 +270,7 @@ " [f out-path & in-paths] (->interceptor - :id :enrich + :id :on-changes :after (fn on-change-after [context] (let [new-db (get-effect context :db) From 4bba2315487dab7fa9ad57c98d4bdc445f54d9fc Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 22:42:45 +1100 Subject: [PATCH 22/33] Add more comments to todomvc --- examples/todomvc/src/todomvc/core.cljs | 26 ++++++++-- examples/todomvc/src/todomvc/db.cljs | 13 +++-- examples/todomvc/src/todomvc/events.cljs | 35 +++++++------ examples/todomvc/src/todomvc/subs.cljs | 14 +++--- examples/todomvc/src/todomvc/views.cljs | 62 +++++++++++------------- 5 files changed, 87 insertions(+), 63 deletions(-) diff --git a/examples/todomvc/src/todomvc/core.cljs b/examples/todomvc/src/todomvc/core.cljs index effcf37a9..dbc9d4330 100644 --- a/examples/todomvc/src/todomvc/core.cljs +++ b/examples/todomvc/src/todomvc/core.cljs @@ -14,10 +14,15 @@ ;; -- Debugging aids ---------------------------------------------------------- (devtools/install!) ;; we love https://github.com/binaryage/cljs-devtools -(enable-console-print!) ;; so println writes to console.log +(enable-console-print!) ;; so that println writes to `console.log` ;; -- Routes and History ------------------------------------------------------ - +;; Although we use the secretary library below, that's mostly a historical +;; accident. You might also consider using: +;; - https://github.com/DomKM/silk +;; - https://github.com/juxt/bidi +;; We don't have a strong opinion. +;; (defroute "/" [] (dispatch [:set-showing :all])) (defroute "/:filter" [filter] (dispatch [:set-showing (keyword filter)])) @@ -29,10 +34,23 @@ ;; -- Entry Point ------------------------------------------------------------- - +;; Within ../../resources/public/index.html you'll see this code +;; window.onload = function () { +;; todomvc.core.main(); +;; } +;; So this is the entry function that kicks off the app once the HTML is loaded. +;; (defn ^:export main [] + ;; Put an initial value into app-db. + ;; The event handler for `:initialise-db` can be found in `events.cljs` + ;; Using the sync version of dispatch means that value is in + ;; place before we go onto the next step. (dispatch-sync [:initialise-db]) - (reagent/render [todomvc.views/todo-app] + + ;; Render the UI into the HTML's
element + ;; The view function `todomvc.views/todo-app` is the + ;; root view for the entire UI. + (reagent/render [todomvc.views/todo-app] ;; (.getElementById js/document "app"))) diff --git a/examples/todomvc/src/todomvc/db.cljs b/examples/todomvc/src/todomvc/db.cljs index 2473319bf..e7bdb726e 100644 --- a/examples/todomvc/src/todomvc/db.cljs +++ b/examples/todomvc/src/todomvc/db.cljs @@ -38,7 +38,7 @@ ;; ;; When the application first starts, this will be the value put in app-db ;; Unless, or course, there are todos in the LocalStore (see further below) -;; Look in core.cljs for "(dispatch-sync [:initialise-db])" +;; Look in `core.cljs` for "(dispatch-sync [:initialise-db])" ;; (def default-value ;; what gets put into app-db by default. @@ -50,16 +50,19 @@ ;; ;; Part of the todomvc challenge is to store todos in LocalStorage, and ;; on app startup, reload the todos from when the program was last run. -;; But we are not to load the setting for the "showing" filter. Just the todos. +;; But the challenge stipulates to NOT load the setting for the "showing" +;; filter. Just the todos. ;; -(def ls-key "todos-reframe") ;; localstore key - +(def ls-key "todos-reframe") ;; localstore key (defn todos->local-store "Puts todos into localStorage" [todos] - (.setItem js/localStorage ls-key (str todos))) ;; sorted-map writen as an EDN map + (.setItem js/localStorage ls-key (str todos))) ;; sorted-map writen as an EDN map + +;; register a coeffect handler which will load a value from localstore +;; To see it used look in events.clj at the event handler for `:initialise-db` (re-frame/reg-cofx :local-store-todos (fn [cofx _] diff --git a/examples/todomvc/src/todomvc/events.cljs b/examples/todomvc/src/todomvc/events.cljs index 3d32be9cb..83a7bcd2a 100644 --- a/examples/todomvc/src/todomvc/events.cljs +++ b/examples/todomvc/src/todomvc/events.cljs @@ -8,12 +8,9 @@ ;; -- Interceptors -------------------------------------------------------------- ;; -;; XXX Add URL for docs here -;; XXX figure out first time spec error -;; XXX seems to be a bug if you refresh the page, and other than "All" is selected. (defn check-and-throw - "throw an exception if db doesn't match the spec." + "throw an exception if db doesn't match the spec" [a-spec db] (when-not (s/valid? a-spec db) (throw (ex-info (str "spec check failed: " (s/explain-str a-spec db)) {})))) @@ -28,8 +25,10 @@ ;; we attach it to each event handler which could update todos (def ->local-store (after todos->local-store)) - -;; the chain of interceptors we use for all handlers that manipulate todos +;; Each event handler can have its own set of interceptors (middleware) +;; But we use the same set of interceptors for all event habdlers related +;; to manipulating todos. +;; A chain of interceptors is a vector. (def todo-interceptors [check-spec-interceptor ;; ensure the spec is still valid (path :todos) ;; 1st param to handler will be the value from this path ->local-store ;; write todos to localstore @@ -49,22 +48,23 @@ ;; -- Event Handlers ---------------------------------------------------------- -;; XXX make localstore a coeffect interceptor - - ;; usage: (dispatch [:initialise-db]) +;; usage: (dispatch [:initialise-db]) (reg-event-fx ;; on app startup, create initial state :initialise-db ;; event id being handled - [(inject-cofx :local-store-todos) + [(inject-cofx :local-store-todos) ;; obtain todos from localstore check-spec-interceptor] ;; after the event handler runs, check that app-db matches the spec (fn [{:keys [db local-store-todos]} _] ;; the handler being registered {:db (assoc default-value :todos local-store-todos)})) ;; all hail the new state - ;; usage: (dispatch [:set-showing :active]) +;; usage: (dispatch [:set-showing :active]) (reg-event-db ;; this handler changes the todo filter :set-showing ;; event-id - [check-spec-interceptor (path :showing) trim-v] ;; this collection of interceptors wrap the handler + ;; this chain of two interceptors wrap the handler + [check-spec-interceptor (path :showing) trim-v] + + ;; The event handler ;; Because of the path interceptor above, the 1st parameter to ;; the handler below won't be the entire 'db', and instead will ;; be the value at a certain path within db, namely :showing. @@ -74,11 +74,18 @@ new-filter-kw)) ;; return new state for the path - ;; usage: (dispatch [:add-todo "Finish comments"]) +;; usage: (dispatch [:add-todo "Finish comments"]) (reg-event-db ;; given the text, create a new todo :add-todo + + ;; The standard set of interceptors, defined above, which we + ;; apply to all todos-modifiing event handlers. Looks after + ;; writing todos to local store, etc. todo-interceptors - (fn [todos [text]] ;; the "path" interceptor in `todo-interceptors` means 1st parameter is :todos + + ;; The event handler function. + ;; The "path" interceptor in `todo-interceptors` means 1st parameter is :todos + (fn [todos [text]] (let [id (allocate-next-id todos)] (assoc todos id {:id id :title text :done false})))) diff --git a/examples/todomvc/src/todomvc/subs.cljs b/examples/todomvc/src/todomvc/subs.cljs index d2c3453ce..ba0c55c01 100644 --- a/examples/todomvc/src/todomvc/subs.cljs +++ b/examples/todomvc/src/todomvc/subs.cljs @@ -2,18 +2,18 @@ (:require [re-frame.core :refer [reg-sub subscribe]])) ;; ------------------------------------------------------------------------------------- -;; Layer 2 (see the infographic for meaning) +;; Layer 2 (see the Subscriptions Infographic for meaning) ;; (reg-sub :showing (fn [db _] ;; db is the (map) value in app-db (:showing db))) ;; I repeat: db is a value. Not a ratom. And this fn does not return a reaction, just a value. -;; so that `fn` is a pure function +;; that `fn` is a pure function ;; Next, the registration of a similar handler is done in two steps. ;; First, we `defn` a pure handler function. Then, we use `reg-sub` to register it. -;; Two steps. This is different to the first registration, which was done in one step. +;; Two steps. This is different to that first registration, above, which was done in one step. (defn sorted-todos [db _] (:todos db)) @@ -79,10 +79,14 @@ ;; - the second function (which is the computation, destructures this 2-vector as its first parameter) (reg-sub :visible-todos - (fn [query-v _] ;; returns a vector of two signals. + + ;; signal function + ;; returns a vector of two input signals + (fn [query-v _] [(subscribe [:todos]) (subscribe [:showing])]) + ;; computation function (fn [[todos showing] _] ;; that 1st parameter is a 2-vector of values (let [filter-fn (case showing :active (complement :done) @@ -109,8 +113,6 @@ ;; Now for some syntactic sugar... ;; The purpose of the sugar is to remove boilerplate noise. To distill to the essential ;; in 90% of cases. -;; Is this a good idea? -;; If it is a good idea, is this good syntax? ;; Because it is so common to nominate 1 or more input signals, ;; reg-sub provides some macro sugar so you can nominate a very minimal ;; vector of input signals. The 1st function is not needed. diff --git a/examples/todomvc/src/todomvc/views.cljs b/examples/todomvc/src/todomvc/views.cljs index 35e745a56..53880412d 100644 --- a/examples/todomvc/src/todomvc/views.cljs +++ b/examples/todomvc/src/todomvc/views.cljs @@ -49,42 +49,38 @@ (defn task-list [] - (let [visible-todos (subscribe [:visible-todos]) - all-complete? (subscribe [:all-complete?])] - (fn [] + (let [visible-todos @(subscribe [:visible-todos]) + all-complete? @(subscribe [:all-complete?])] [:section#main [:input#toggle-all {:type "checkbox" - :checked @all-complete? - :on-change #(dispatch [:complete-all-toggle (not @all-complete?)])}] + :checked all-complete? + :on-change #(dispatch [:complete-all-toggle (not all-complete?)])}] [:label {:for "toggle-all"} "Mark all as complete"] [:ul#todo-list - (for [todo @visible-todos] - ^{:key (:id todo)} [todo-item todo])]]))) + (for [todo visible-todos] + ^{:key (:id todo)} [todo-item todo])]])) (defn footer-controls [] - (let [footer-stats (subscribe [:footer-counts]) - showing (subscribe [:showing])] - (fn [] - (let [[active done] @footer-stats - a-fn (fn [filter-kw txt] - [:a {:class (when (= filter-kw @showing) "selected") + (let [[active done] @(subscribe [:footer-counts]) + showing @(subscribe [:showing]) + a-fn (fn [filter-kw txt] + [:a {:class (when (= filter-kw showing) "selected") :href (str "#/" (name filter-kw))} txt])] - [:footer#footer - - [:span#todo-count - [:strong active] " " (case active 1 "item" "items") " left"] - [:ul#filters - [:li (a-fn :all "All")] - [:li (a-fn :active "Active")] - [:li (a-fn :done "Completed")]] - (when (pos? done) - [:button#clear-completed {:on-click #(dispatch [:clear-completed])} - "Clear completed"])])))) + [:footer#footer + [:span#todo-count + [:strong active] " " (case active 1 "item" "items") " left"] + [:ul#filters + [:li (a-fn :all "All")] + [:li (a-fn :active "Active")] + [:li (a-fn :done "Completed")]] + (when (pos? done) + [:button#clear-completed {:on-click #(dispatch [:clear-completed])} + "Clear completed"])])) (defn task-entry @@ -99,13 +95,11 @@ (defn todo-app [] - (let [todos (subscribe [:todos])] - (fn [] - [:div - [:section#todoapp - [task-entry] - (when (seq @todos) - [task-list]) - [footer-controls]] - [:footer#info - [:p "Double-click to edit a todo"]]]))) + [:div + [:section#todoapp + [task-entry] + (when (seq @(subscribe [:todos])) + [task-list]) + [footer-controls]] + [:footer#info + [:p "Double-click to edit a todo"]]]) From ae7da52088902054b5bbda07ad684792b8b3015c Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Wed, 28 Dec 2016 23:36:12 +1100 Subject: [PATCH 23/33] Improve docs --- docs/Subscribing-To-External-Data.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/Subscribing-To-External-Data.md b/docs/Subscribing-To-External-Data.md index 41b923da0..0d63ae8b9 100644 --- a/docs/Subscribing-To-External-Data.md +++ b/docs/Subscribing-To-External-Data.md @@ -143,9 +143,9 @@ Enough fluffing about with words, here's a code sketch for our subscription hand A few things to notice: -1. We are using the low level `reg-sub-raw` registration for our handler (and not `reg-sub`). - This gives us some low level control. `app-db` will be an atom. We must return a - `reaction` (signal). [See the `reg-sub-raw` docs at the end of this tutorial](SubscriptionFlow.md) +1. We are using the low level `reg-sub-raw` to register our handler (and not the more normal `reg-sub`) + so we can get an `:on-dispose` callback when the subscription is no longer needed. + [See the `reg-sub-raw` docs at the end of this tutorial](SubscriptionFlow.md) 2. You have to write `issue-items-query!`. Are you making a Restful GET? Are you writing JSON packets down a websocket? The query has to be made. @@ -239,12 +239,10 @@ Within this document the first alternative has been given more word count only because there's a few more tricks to make it work, not because it is necessarily preferred. -## What Not To Do - -Don't get into making views source their data directly using React lifecycle methods. +## Absolutely Never Do This Sometimes, because of their background with other JS frameworks, -new re-framers feel like the Components themselves (the views) +new re-framians feel like the Components themselves (the views) should have the responsibility of sourcing the data they need. They then use React lifecycle methods like `:component-did-mount` @@ -252,7 +250,7 @@ to load remote data. I believe this is absolutely the wrong way to do it. -In re-frame we want views to be as simple and dumb as possible. They turn +In re-frame, we want views to be as simple and dumb as possible. They turn data into HTML and nothing more. they absolutely do not do imperative stuff. Use one of the two alternatives described above. From be3f45df8783e2bb9f77ba4510721eba74269f35 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 29 Dec 2016 10:01:23 +1100 Subject: [PATCH 24/33] Better docs navigation --- docs/MentalModelOmnibus.md | 18 ++++++++---------- docs/SubscriptionFlow.md | 6 ++++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index 122070334..9bec1fbef 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -5,16 +5,10 @@ ## Mental Model Omnibus -> If a factory is torn down but the rationality which produced it is -left standing, then that rationality will simply produce another -factory. If a revolution destroys a government, but the systematic -patterns of thought that produced that government are left intact, -then those patterns will repeat themselves.
-> -- Robert Pirsig, Zen and the Art of Motorcycle Maintenance - - +> All models are wrong, but some are useful + The re-frame tutorials initially focus on the **domino narrative**. The goal is to efficiently explain the mechanics of re-frame, and to get you reading and writing code ASAP. @@ -26,8 +20,12 @@ This tutorial is a tour of these ideas, justifications and insights. It is a little rambling, but I'm hoping it will deliver for you at least one "Aaaah, I see" moment before the end. -> All models are wrong, but some are useful -
+> If a factory is torn down but the rationality which produced it is +left standing, then that rationality will simply produce another +factory. If a revolution destroys a government, but the systematic +patterns of thought that produced that government are left intact, +then those patterns will repeat themselves.
+> -- Robert Pirsig, Zen and the Art of Motorcycle Maintenance diff --git a/docs/SubscriptionFlow.md b/docs/SubscriptionFlow.md index e8a6575ac..801bfbef7 100644 --- a/docs/SubscriptionFlow.md +++ b/docs/SubscriptionFlow.md @@ -1,7 +1,9 @@ +> In a rush? You can get away with skipping this page on the first pass.
+> Next page: [Basic App Structure](Basic-App-Structure.md) + ## Flow Mechanics -If you are in a hurry, this tutorial can be skipped. It provides advanced, background information. -It explains the underlying reactive mechanism used in dominoes 4-5-6. +This tutorial explains the underlying reactive mechanism used in dominoes 4-5-6. It goes on to introduce `re-frame.core/reg-sub-raw`. ## On Flow From 767f6a9ee8aa420cf91171323d7cb3be005269ce Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 29 Dec 2016 10:12:50 +1100 Subject: [PATCH 25/33] Wrangle the top of MentalModelOmnibus docs --- docs/MentalModelOmnibus.md | 9 ++++++--- images/mental-model-omnibus.jpg | Bin 22599 -> 32144 bytes 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index 9bec1fbef..d4521d89e 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -250,7 +250,8 @@ know interconnections are often critical to a system. In the case of re-frame, dominoes are the **parts**, so, tick, yes, we have looked at them first. Our brains are happy. But what about the **interconnections**? -If the **parts** are functions, what does it even mean to talk about **interconnections between functions?** +If the **parts** are functions, as is the case with re-frame, +what does it even mean to talk about **interconnections between functions?** To answer that question, I'll rephrase it as: how are the domino functions **composed**? @@ -277,8 +278,10 @@ composition in terms of data flow**. re-frame delivers architecture by supplying the interconnections - it threads the data - it composes the dominoes - it is the lines between the boxes. -But re-frame has no universal method for this. The technique it uses varies from one domino neighbour -pair to the next. +But it has no universal method for this. The technique it uses varies from one domino neighbour +pair to the next. Initially, it uses a queue/router, then a pipeline of interceptors +and finally a Signal Graph. + ## Full Stack diff --git a/images/mental-model-omnibus.jpg b/images/mental-model-omnibus.jpg index 47cc51a22d7cbedac2e47d004835cfea6f9cd9e0..17b0274b3f86db6f0e3fdeec1233435ff7c95257 100644 GIT binary patch literal 32144 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 aVdVSg!~bkN_JhRYAItjx+K8C`=>K0RYFy(0 literal 22599 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 KsOe+=e-i+EBLAxZ From fcd0db5d32f2ca6b1a8b084775b556f3080c741c Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 29 Dec 2016 10:22:11 +1100 Subject: [PATCH 26/33] Get image position correct in docs (relative to github rendering) --- docs/MentalModelOmnibus.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index d4521d89e..c9a3f1ced 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -5,7 +5,7 @@ ## Mental Model Omnibus - + > All models are wrong, but some are useful From 2a8e5dcfac56eaa3c735dace8275c0896fb0a5c3 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 29 Dec 2016 11:05:15 +1100 Subject: [PATCH 27/33] Improve Table of Contexts in various docs --- docs/CodeWalkthrough.md | 21 ++++++--------------- docs/Coeffects.md | 26 +++++++++++++------------- docs/Effects.md | 4 ---- docs/Interceptors.md | 18 ++++++++---------- docs/MentalModelOmnibus.md | 8 +++++--- docs/Subscribing-To-External-Data.md | 26 +++++++++++++------------- docs/SubscriptionsCleanup.md | 5 +++++ 7 files changed, 50 insertions(+), 58 deletions(-) diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index df1397828..d40047936 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -20,32 +20,24 @@ In this tutorial, **we'll look at re-frame code**. - [Namespace](#namespace) - [Data Schema](#data-schema) - [Events (domino 1)](#events-domino-1) - - [dispatch](#dispatch) - - [After dispatch](#after-dispatch) - [Event Handlers (domino 2)](#event-handlers-domino-2) - - [reg-event-db](#reg-event-db) - - [:initialize](#initialize) - - [:timer](#timer) - - [:time-color-change](#time-color-change) - [Effect Handlers (domino 3)](#effect-handlers-domino-3) - [Subscription Handlers (domino 4)](#subscription-handlers-domino-4) - - [reg-sub](#reg-sub) - [View Functions (domino 5)](#view-functions-domino-5) - - [Hiccup](#hiccup) ## What Code? -This repo contains an example application called ["simple"](https://github.com/Day8/re-frame/tree/develop/examples/simple), -which has around 70 lines of code. We'll look at every line of [the file](https://github.com/Day8/re-frame/blob/develop/examples/simple/src/simple/core.cljs). +This repo contains an `/examples` application called ["simple"](https://github.com/Day8/re-frame/tree/develop/examples/simple), +which contains 70 lines of code. We'll look at every line of [the file](https://github.com/Day8/re-frame/blob/develop/examples/simple/src/simple/core.cljs). This app: - displays the current time in a nice big, colourful font - provides a single text input field, into which you can type a hex colour code, like "#CCC", used for the time display -Here's what it looks like: +When it is running, here's what it looks like: ![Example App image](../images/example_app.png) @@ -93,7 +85,7 @@ to your various handlers as required. ## Events (domino 1) -Events are data. You choose the format. +Events are data. re-frame uses a vector format for events. For example: @@ -107,14 +99,13 @@ associated with the event. The additional value above, `42`, is presumably the id of the item to delete. Here are some other example events: - ```clj [:admit-to-being-satoshi false] [:dressing/put-pants-on "velour flares" {:method :left-leg-first :belt false}] ``` -The `kind` of event is always a keyword, and for non-trivial -applications it tends to be namespaced. +The `kind` of event is a keyword, and for non-trivial +applications it will be namespaced. **Rule**: events are pure data. No sneaky tricks like putting callback functions on the wire. You know who you are. diff --git a/docs/Coeffects.md b/docs/Coeffects.md index 156355355..316c49b45 100644 --- a/docs/Coeffects.md +++ b/docs/Coeffects.md @@ -9,19 +9,19 @@ to manage them in tests. ### Table Of Contents -- [What Are They?](#what-are-they) -- [An Example](#an-example) -- [How We Want It](#how-we-want-it) -- [Abracadabra](#abracadabra) -- [Which Interceptors?](#which-interceptors) -- [`inject-cofx`](#inject-cofx) -- [More `inject-cofx`](#more-inject-cofx) -- [Meet `reg-cofx`](#meet-reg-cofx) -- [Example Of `reg-cofx`](#example-of-reg-cofx) -- [Another Example Of `reg-cofx`](#another-example-of-reg-cofx) -- [Secret Interceptors](#secret-interceptors) -- [Testing](#testing) -- [The 5 Point Summary](#the-5-point-summary) +* [What Are They?](#what-are-they-) +* [An Example](#an-example) +* [How We Want It](#how-we-want-it) +* [Abracadabra](#abracadabra) +* [Which Interceptors?](#which-interceptors-) +* [`inject-cofx`](#-inject-cofx-) +* [More `inject-cofx`](#more--inject-cofx-) +* [Meet `reg-cofx`](#meet--reg-cofx-) +* [Example Of `reg-cofx`](#example-of--reg-cofx-) +* [Another Example Of `reg-cofx`](#another-example-of--reg-cofx-) +* [Secret Interceptors](#secret-interceptors) +* [Testing](#testing) +* [The 5 Point Summary](#the-5-point-summary) diff --git a/docs/Effects.md b/docs/Effects.md index d9440c88d..813231463 100644 --- a/docs/Effects.md +++ b/docs/Effects.md @@ -6,10 +6,6 @@ This tutorial explains how side effects are actioned, how you can create your own side effects, and how you can make side effects a noop in event replays. -> imperative programming is a big pile of do
->     -- @stuarthalloway - - ### Table Of Contents diff --git a/docs/Interceptors.md b/docs/Interceptors.md index d5db3968f..9377512af 100644 --- a/docs/Interceptors.md +++ b/docs/Interceptors.md @@ -6,24 +6,22 @@ This is a tutorial on re-frame Interceptors. It explains exactly how events get ### Table Of Contents -- [Introduction](#introduction) -- [Interceptors](#interceptors) - - [Why Interceptors?](#why-interceptors) - - [What Do Interceptors Do?](#what-do-interceptors-do) - - [Wait, I know That Pattern!](#wait-i-know-that-pattern) - - [What's In The Pipeline?](#whats-in-the-pipeline) - - [Show Me](#show-me) - - [Handlers Are Interceptors Too](#handlers-are-interceptors-too) +- [Why Interceptors?](#why-interceptors-) +- [What Do Interceptors Do?](#what-do-interceptors-do-) +- [Wait, I know That Pattern!](#wait--i-know-that-pattern-) +- [What's In The Pipeline?](#what-s-in-the-pipeline-) +- [Show Me](#show-me) +- [Handlers Are Interceptors Too](#handlers-are-interceptors-too) - [Executing A Chain](#executing-a-chain) - [The Links Of The Chain](#the-links-of-the-chain) - - [What Is Context?](#what-is-context) + - [What Is Context?](#what-is-context-) - [Self Modifying](#self-modifying) - [Credit](#credit) - [Write An Interceptor](#write-an-interceptor) - [Wrapping Handlers](#wrapping-handlers) - [Summary](#summary) - [Appendix](#appendix) - - [The Builtin Interceptors](#the-builtin-interceptors) + - [The Built-in Interceptors](#the-built-in-interceptors) diff --git a/docs/MentalModelOmnibus.md b/docs/MentalModelOmnibus.md index c9a3f1ced..03e2fb16a 100644 --- a/docs/MentalModelOmnibus.md +++ b/docs/MentalModelOmnibus.md @@ -30,16 +30,18 @@ then those patterns will repeat themselves.
-## Table Of Contents +### Table Of Contents -- [What is the problem?](#what-is-the-problem) +- [What is the problem?](#what-is-the-problem-) - [Guiding Philosophy](#guiding-philosophy) - [It does Event Sourcing](#it-does-event-sourcing) - [It does a reduce](#it-does-a-reduce) - [Derived Data All The Way Down](#derived-data-all-the-way-down) - [It does FSM](#it-does-fsm) +- [Interconnections](#interconnections) - [Full Stack](#full-stack) -- [What Of This Romance?](#what-of-this-romance) +- [What Of This Romance?](#what-of-this-romance-) + diff --git a/docs/Subscribing-To-External-Data.md b/docs/Subscribing-To-External-Data.md index 0d63ae8b9..207129813 100644 --- a/docs/Subscribing-To-External-Data.md +++ b/docs/Subscribing-To-External-Data.md @@ -3,18 +3,18 @@ ## Table Of Contents - [Subscribing to External Data](#subscribing-to-external-data) - - [There Can Be Only One!!](#there-can-be-only-one) - - [Components Don't Know, Don't Care](#components-dont-know-dont-care) - - [A 2nd Source](#a-2nd-source) - - [Via A Subscription](#via-a-subscription) - - [The Subscription Handler's Job](#the-subscription-handlers-job) - - [Some Code](#some-code) - - [Any Good?](#any-good) - - [Warning: Undo/Redo](#warning-undoredo) - - [Query De-duplication](#query-de-duplication) - - [Thanks To](#thanks-to) -- [The Alternative Approach](#the-alternative--approach) -- [What Not To Do](#what-not-to-do) + * [There Can Be Only One!!](#there-can-be-only-one--) + * [Components Don't Know, Don't Care](#components-don-t-know--don-t-care) + * [A 2nd Source](#a-2nd-source) + * [Via A Subscription](#via-a-subscription) + * [The Subscription Handler's Job](#the-subscription-handler-s-job) + * [Some Code](#some-code) + * [Any Good?](#any-good-) + * [Warning: Undo/Redo](#warning--undo-redo) + * [Query De-duplication](#query-de-duplication) + * [Thanks To](#thanks-to) +- [The Alternative Approach](#the-alternative-approach) +- [Absolutely Never Do This](#absolutely-never-do-this) @@ -213,7 +213,7 @@ in `issue-items-query!` itself. You can @nidu for his valuable review comments and insights -## The Alternative Approach +## The Alternative Approach Event handlers do most of the heavy lifting within re-frame apps. diff --git a/docs/SubscriptionsCleanup.md b/docs/SubscriptionsCleanup.md index 295609831..ba96c092f 100644 --- a/docs/SubscriptionsCleanup.md +++ b/docs/SubscriptionsCleanup.md @@ -162,3 +162,8 @@ This feature shakes out nicely because re-frame has a data oriented design. Previous: [Infographic](SubscriptionInfographic.md)       Up: [Index](README.md)       Next: [Flow Mechanics](SubscriptionFlow.md)        + + + + + From 9b748229ed43f077f2293e178ed0b22bc3308cc7 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 29 Dec 2016 18:01:12 +1100 Subject: [PATCH 28/33] Improve "simple" example --- docs/CodeWalkthrough.md | 18 +++++++++++------- examples/simple/README.md | 3 +++ examples/simple/src/simple/core.cljs | 5 ++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/CodeWalkthrough.md b/docs/CodeWalkthrough.md index d40047936..4be58a767 100644 --- a/docs/CodeWalkthrough.md +++ b/docs/CodeWalkthrough.md @@ -2,14 +2,13 @@ ## Initial Code Walk-through -At this point, you are about 50% of the way to understanding re-frame. You are armed with: - - a high level understanding of the 6 domino process (from re-frame's README) - - an understanding of application state (from the previous tutorial) +At this point, you are about 50% of the way to understanding re-frame. You have: + - an overview of the 6 domino process [from this repo's README](../README.md) + - an understanding of app state ([from the previous tutorial)](ApplicationState.md)) -By the end of this tutorial, you'll be at 70%, which is good +In this tutorial, **we look at re-frame code**. By the end of it, you'll be at 70% knowledge, which is good enough to start coding by yourself. -In this tutorial, **we'll look at re-frame code**. @@ -41,7 +40,7 @@ When it is running, here's what it looks like: ![Example App image](../images/example_app.png) -To run the code: +To run the code yourself: * Install Java 8 * Install leiningen (http://leiningen.org/#install) @@ -49,7 +48,12 @@ Then: 1. `git clone https://github.com/Day8/re-frame.git` 2. `cd re-frame/examples/simple` 3. `lein do clean, figwheel` - 4. open http://localhost:3449/example.html + 4. wait a minute and then open `http://localhost:3449/example.html` + +So, what's just happened? The ClojureScript code under `src` has been compiled across to `javascript` and +put into `/resources/public/js/client.js` which is loaded into `/resources/public/example.html` (the HTML you just openned) + +Figwheel provides for hot-loading, so you can edit the source and watch the loaded HTML change. ## Namespace diff --git a/examples/simple/README.md b/examples/simple/README.md index f1cea9e7c..f46eddead 100644 --- a/examples/simple/README.md +++ b/examples/simple/README.md @@ -2,6 +2,9 @@ This tiny application is meant to provide a quick start of the basics of re-frame. +A detailed source code walk-through is provided in the docs: +https://github.com/Day8/re-frame/blob/master/docs/CodeWalkthrough.md + All the code is in one namespace `/src/simpleexample/core.cljs` ### Run It And Change It diff --git a/examples/simple/src/simple/core.cljs b/examples/simple/src/simple/core.cljs index b199981ce..917b0a246 100644 --- a/examples/simple/src/simple/core.cljs +++ b/examples/simple/src/simple/core.cljs @@ -2,6 +2,9 @@ (:require [reagent.core :as reagent] [re-frame.core :as rf])) +;; A detailed walk-through of this source code is provied in the docs: +;; https://github.com/Day8/re-frame/blob/master/docs/CodeWalkthrough.md + ;; -- Domino 1 - Event Dispatch ----------------------------------------------- (defn dispatch-timer-event @@ -25,7 +28,7 @@ (rf/reg-event-db ;; usage: (dispatch [:time-color-change 34562]) - :time-color-change ;; dispatched when the user enters a new colour into the UI + :time-color-change ;; dispatched when the user enters a new colour into the UI text field (fn [db [_ new-color-value]] ;; -db event handlers given 2 parameters: current application state and event (a vector) (assoc db :time-color new-color-value))) ;; compute and return the new application state From ab54e2fab2e4f3c565f7128073a653902e0f2a44 Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Mon, 19 Dec 2016 18:30:42 +0800 Subject: [PATCH 29/33] move registry and event-queue state into re-frame.core --- src/re_frame/cofx.cljc | 34 ++- src/re_frame/core.cljc | 43 ++-- src/re_frame/events.cljc | 15 +- src/re_frame/fx.cljc | 175 ++++++++-------- src/re_frame/registry.cljc | 61 ++++++ src/re_frame/router.cljc | 15 +- src/re_frame/std_interceptors.cljc | 1 - src/re_frame/subs.cljc | 31 +-- test/re-frame/restore_test.cljs | 4 +- test/re-frame/subs_test.cljs | 318 ++++++++++++++++------------- 10 files changed, 404 insertions(+), 293 deletions(-) create mode 100644 src/re_frame/registry.cljc diff --git a/src/re_frame/cofx.cljc b/src/re_frame/cofx.cljc index 819f5ed7d..b37adeb0f 100644 --- a/src/re_frame/cofx.cljc +++ b/src/re_frame/cofx.cljc @@ -2,15 +2,14 @@ (:require [re-frame.db :refer [app-db]] [re-frame.interceptor :refer [->interceptor]] - [re-frame.registrar :refer [get-handler clear-handlers register-handler]] + [re-frame.registry :as reg] [re-frame.loggers :refer [console]])) ;; -- Registration ------------------------------------------------------------ (def kind :cofx) -(assert (re-frame.registrar/kinds kind)) -(def register (partial register-handler kind)) +(assert (re-frame.registry/kinds kind)) ;; -- Interceptor ------------------------------------------------------------- @@ -36,33 +35,30 @@ the current value of `:coeffects` and, optionally, the value. The registered handler is expected to return a modified coeffect. " - ([id] + ([registry id] (->interceptor :id :coeffects :before (fn coeffects-before [context] - (update context :coeffects (get-handler kind id))))) - ([id value] + (update context :coeffects (reg/get-handler registry kind id))))) + ([registry id value] (->interceptor :id :coeffects :before (fn coeffects-before [context] - (update context :coeffects (get-handler kind id) value))))) + (update context :coeffects (reg/get-handler registry 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))) - +(defn register-built-in! + [registry] + (let [register (partial reg/register-handler registry kind)] + (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)) - - +;; (def inject-db (inject-cofx :db)) diff --git a/src/re_frame/core.cljc b/src/re_frame/core.cljc index da13510db..3638be4ff 100644 --- a/src/re_frame/core.cljc +++ b/src/re_frame/core.cljc @@ -9,6 +9,7 @@ [re-frame.router :as router] [re-frame.loggers :as loggers] [re-frame.registrar :as registrar] + [re-frame.registry :as reg] [re-frame.interceptor :as interceptor] [re-frame.std-interceptors :as std-interceptors :refer [db-handler->interceptor fx-handler->interceptor @@ -16,9 +17,13 @@ [clojure.set :as set])) +;; -- state +(def registry (reg/make-registry)) +(def ev-queue (router/->EventQueue :idle interop/empty-queue {} registry)) + ;; -- dispatch -(def dispatch router/dispatch) -(def dispatch-sync router/dispatch-sync) +(def dispatch (partial router/dispatch ev-queue)) +(def dispatch-sync (partial router/dispatch-sync ev-queue registry)) ;; XXX move API functions up to this core level - to enable code completion and docs @@ -53,26 +58,30 @@ This is a low level, advanced function. You should probably be using reg-sub instead." [query-id handler-fn] - (registrar/register-handler subs/kind query-id handler-fn)) + (reg/register-handler registry subs/kind query-id handler-fn)) -(def reg-sub subs/reg-sub) -(def subscribe subs/subscribe) +(def reg-sub (partial subs/reg-sub registry)) +(def subscribe (partial subs/subscribe registry)) -(def clear-sub (partial registrar/clear-handlers subs/kind)) +(def clear-sub (partial reg/clear-handlers registry subs/kind)) (def clear-subscription-cache! subs/clear-subscription-cache!) ;; -- effects -(def reg-fx fx/register) -(def clear-fx (partial registrar/clear-handlers fx/kind)) +(def reg-fx (partial reg/register-handler registry fx/kind)) +(def clear-fx (partial reg/clear-handlers registry fx/kind)) +(def fx-do-fx (fx/do-fx registry)) +(fx/register-built-in! registry ev-queue) ;; -- coeffects -(def reg-cofx cofx/register) -(def inject-cofx cofx/inject-cofx) -(def clear-cofx (partial registrar/clear-handlers cofx/kind)) +(def reg-cofx (partial reg/register-handler registry cofx/kind)) +(def inject-cofx (partial cofx/inject-cofx registry)) +(def clear-cofx (partial reg/clear-handlers registry cofx/kind)) +(def cofx-inject-db (cofx/inject-cofx registry :db)) +(cofx/register-built-in! registry) ;; -- Events -(def clear-event (partial registrar/clear-handlers events/kind)) +(def clear-event (partial reg/clear-handlers registry events/kind)) (defn reg-event-db "Register the given `id`, typically a keyword, with the combination of @@ -86,21 +95,21 @@ ([id db-handler] (reg-event-db id nil db-handler)) ([id interceptors db-handler] - (events/register id [cofx/inject-db fx/do-fx interceptors (db-handler->interceptor db-handler)]))) + (events/register registry id [cofx-inject-db fx-do-fx interceptors (db-handler->interceptor db-handler)]))) (defn reg-event-fx ([id fx-handler] (reg-event-fx id nil fx-handler)) ([id interceptors fx-handler] - (events/register id [cofx/inject-db fx/do-fx interceptors (fx-handler->interceptor fx-handler)]))) + (events/register registry id [cofx-inject-db fx-do-fx interceptors (fx-handler->interceptor fx-handler)]))) (defn reg-event-ctx ([id handler] (reg-event-ctx id nil handler)) ([id interceptors handler] - (events/register id [cofx/inject-db fx/do-fx interceptors (ctx-handler->interceptor handler)]))) + (events/register registry id [cofx-inject-db fx-do-fx interceptors (ctx-handler->interceptor handler)]))) ;; -- Logging ----- @@ -168,12 +177,12 @@ ([f] (add-post-event-callback f f)) ;; use f as its own identifier ([id f] - (router/add-post-event-callback re-frame.router/event-queue id f))) + (router/add-post-event-callback ev-queue id f))) (defn remove-post-event-callback [id] - (router/remove-post-event-callback re-frame.router/event-queue id)) + (router/remove-post-event-callback ev-queue id)) ;; -- Deprecation Messages diff --git a/src/re_frame/events.cljc b/src/re_frame/events.cljc index 1808914b4..aba57bbf2 100644 --- a/src/re_frame/events.cljc +++ b/src/re_frame/events.cljc @@ -1,15 +1,14 @@ (ns re-frame.events - (:require [re-frame.db :refer [app-db]] - [re-frame.utils :refer [first-in-vector]] + (:require [re-frame.utils :refer [first-in-vector]] [re-frame.interop :refer [empty-queue debug-enabled?]] - [re-frame.registrar :refer [get-handler register-handler]] + [re-frame.registry :as reg] [re-frame.loggers :refer [console]] [re-frame.interceptor :as interceptor] [re-frame.trace :as trace :include-macros true])) (def kind :event) -(assert (re-frame.registrar/kinds kind)) +(assert (re-frame.registry/kinds kind)) (defn- flatten-and-remove-nils "`interceptors` might have nested collections, and contain nil elements. @@ -40,8 +39,8 @@ before registration. An `event handler` will likely be at the end of the chain (wrapped in an interceptor)." - [id interceptors] - (register-handler kind id (flatten-and-remove-nils id interceptors))) + [registry id interceptors] + (reg/register-handler registry kind id (flatten-and-remove-nils id interceptors))) @@ -51,9 +50,9 @@ (defn handle "Given an event vector, look up the associated intercepter chain, and execute it." - [event-v] + [registry event-v] (let [event-id (first-in-vector event-v)] - (if-let [interceptors (get-handler kind event-id true)] + (if-let [interceptors (reg/get-handler registry kind event-id true)] (if *handling* (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] diff --git a/src/re_frame/fx.cljc b/src/re_frame/fx.cljc index a7b8191b2..57e389957 100644 --- a/src/re_frame/fx.cljc +++ b/src/re_frame/fx.cljc @@ -5,19 +5,19 @@ [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.registry :as reg] [re-frame.loggers :refer [console]])) ;; -- Registration ------------------------------------------------------------ (def kind :fx) -(assert (re-frame.registrar/kinds kind)) -(def register (partial register-handler kind)) +(assert (re-frame.registry/kinds kind)) +;; (def register (partial register-handler kind)) ;; -- Interceptor ------------------------------------------------------------- -(def do-fx +(defn do-fx "An interceptor which actions a `context's` (side) `:effects`. For each key in the `:effects` map, call the `effects handler` previously @@ -29,94 +29,99 @@ :undo \"set flag\"} call the registered effects handlers for each of the map's keys: `:dispatch`, `:undo` and `:db`." + [registry] (->interceptor :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)] + (if-let [effect-fn (reg/get-handler registry kind effect-k true)] (effect-fn value)))))) ;; -- Builtin Effect Handlers ------------------------------------------------ -;; :dispatch-later -;; -;; `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 - (fn [value] - (doseq [{:keys [ms dispatch] :as effect} value] - (if (or (empty? dispatch) (not (number? ms))) - (console :error "re-frame: ignoring bad :dispatch-later value:" effect) - (set-timeout! #(router/dispatch dispatch) ms))))) - - -;; :dispatch -;; -;; `dispatch` one event. Excepts a single vector. -;; -;; usage: -;; {:dispatch [:event-id "param"] } - -(register - :dispatch - (fn [value] - (if-not (vector? value) - (console :error "re-frame: ignoring bad :dispatch value. Expected a vector, but got:" value) - (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 - (fn [value] - (if-not (sequential? value) - (console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got:" value)) - (doseq [event value] (router/dispatch event)))) - - -;; :deregister-event-handler -;; -;; removes a previously registered event handler. Expects either a single id ( -;; typically a keyword), or a seq of ids. -;; -;; usage: -;; {:deregister-event-handler :my-id)} -;; or: -;; {:deregister-event-handler [:one-id :another-id]} -;; -(register - :deregister-event-handler - (fn [value] - (let [clear-event (partial clear-handlers events/kind)] - (if (sequential? value) - (doseq [event (if (sequential? value) value [value])] - (clear-event event)))))) - - -;; :db -;; -;; reset! app-db with a new value. Expects a map. -;; -;; usage: -;; {:db {:key1 value1 key2 value2}} -;; -(register - :db - (fn [value] - (reset! app-db value))) +(defn register-built-in! + [registry event-queue] + (let [register (partial reg/register-handler registry kind)] + + ;; :dispatch-later + ;; + ;; `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 + (fn [value] + (doseq [{:keys [ms dispatch] :as effect} value] + (if (or (empty? dispatch) (not (number? ms))) + (console :error "re-frame: ignoring bad :dispatch-later value:" effect) + (set-timeout! #(router/dispatch event-queue dispatch) ms))))) + + + ;; :dispatch + ;; + ;; `dispatch` one event. Excepts a single vector. + ;; + ;; usage: + ;; {:dispatch [:event-id "param"] } + ;; + (register + :dispatch + (fn [value] + (if-not (vector? value) + (console :error "re-frame: ignoring bad :dispatch value. Expected a vector, but got:" value) + (router/dispatch event-queue 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 + (fn [value] + (if-not (sequential? value) + (console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got:" value)) + (doseq [event value] (router/dispatch event-queue event)))) + + + ;; :deregister-event-handler + ;; + ;; removes a previously registered event handler. Expects either a single id ( + ;; typically a keyword), or a seq of ids. + ;; + ;; usage: + ;; {:deregister-event-handler :my-id)} + ;; or: + ;; {:deregister-event-handler [:one-id :another-id]} + ;; + (register + :deregister-event-handler + (fn [value] + (let [clear-event (partial reg/clear-handlers registry events/kind)] + (if (sequential? value) + (doseq [event (if (sequential? value) value [value])] + (clear-event event)))))) + + + ;; :db + ;; + ;; reset! app-db with a new value. Expects a map. + ;; + ;; usage: + ;; {:db {:key1 value1 key2 value2}} + ;; + (register + :db + (fn [value] + (reset! app-db value))))) diff --git a/src/re_frame/registry.cljc b/src/re_frame/registry.cljc new file mode 100644 index 000000000..02def4b33 --- /dev/null +++ b/src/re_frame/registry.cljc @@ -0,0 +1,61 @@ +(ns re-frame.registry + "In many places, re-frame asks you to associate an `id` (keyword) + with a `handler` (function). This namespace contains the + central registry of such associations." + (:require [re-frame.interop :refer [debug-enabled?]] + [re-frame.loggers :refer [console]])) + + +;; kinds of handlers +(def kinds #{:event :fx :cofx :sub}) + +(defprotocol IRegistry + (get-handler + [this kind] + [this kind id] + [this kind id required?]) + + (register-handler + [this kind id handler-fn]) + + (clear-handlers + [this] + [this kind] + [this kind id])) + +(defrecord Registry [kinds kind->id->handler] + IRegistry + (get-handler [this kind] + (get @kind->id->handler kind)) + (get-handler [this kind id] + (get-in @kind->id->handler [kind id])) + (get-handler [this kind id required?] + (let [handler (get-handler this kind id)] + (when debug-enabled? ;; This is in a separate when so Closure DCE can run + (when (and required? (nil? handler)) ;; Otherwise you'd need to type hint the and with a ^boolean for DCE. + (console :error "re-frame: no " (str kind) " handler registered for:" id))) + handler)) + + (register-handler [this kind id handler-fn] + (when debug-enabled? ;; This is in a separate when so Closure DCE can run + (when (get-handler this kind id false) + (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 + + (clear-handlers [this] ;; clear all kinds + (reset! kind->id->handler {})) + (clear-handlers [this kind] ;; clear all handlers for this kind + (assert (kinds kind)) + (swap! kind->id->handler dissoc kind)) + (clear-handlers [this kind id] ;; clear a single handler for a kind + (assert (kinds kind)) + (if (get-handler this kind id) + (swap! kind->id->handler update-in [kind] dissoc id) + (console :warn "re-frame: can't clear" (str kind) "handler for" (str id ". Handler not found."))))) + +(defn make-registry [] + ;; This atom contains a register of all handlers. + ;; Contains a map keyed first by `kind` (of handler), and then `id`. + ;; Leaf nodes are handlers. + (->Registry kinds (atom {}))) \ No newline at end of file diff --git a/src/re_frame/router.cljc b/src/re_frame/router.cljc index 2595d64bb..c3bf35346 100644 --- a/src/re_frame/router.cljc +++ b/src/re_frame/router.cljc @@ -1,5 +1,5 @@ (ns re-frame.router - (:require [re-frame.events :refer [handle]] + (:require [re-frame.events :as ev] [re-frame.interop :refer [after-render empty-queue next-tick]] [re-frame.loggers :refer [console]] [re-frame.trace :as trace :include-macros true])) @@ -92,7 +92,8 @@ ;; Concrete implementation of IEventQueue (deftype EventQueue [#?(:cljs ^:mutable fsm-state :clj ^:volatile-mutable fsm-state) #?(:cljs ^:mutable queue :clj ^:volatile-mutable queue) - #?(:cljs ^:mutable post-event-callback-fns :clj ^:volatile-mutable post-event-callback-fns)] + #?(:cljs ^:mutable post-event-callback-fns :clj ^:volatile-mutable post-event-callback-fns) + registry] IEventQueue ;; -- API ------------------------------------------------------------------ @@ -172,7 +173,7 @@ [this] (let [event-v (peek queue)] (try - (handle event-v) + (ev/handle registry event-v) (set! queue (pop queue)) (-call-post-event-callbacks this event-v) (catch #?(:cljs :default :clj Exception) ex @@ -219,7 +220,7 @@ ;; When "dispatch" is called, the event is added into this event queue. Later, ;; the queue will "run" and the event will be "handled" by the registered function. ;; -(def event-queue (->EventQueue :idle empty-queue {})) +;; (def event-queue (->EventQueue :idle empty-queue {})) ;; --------------------------------------------------------------------------- @@ -235,7 +236,7 @@ Usage: (dispatch [:delete-item 42])" - [event] + [event-queue event] (if (nil? event) (throw (ex-info "re-frame: you called \"dispatch\" without an event vector." {})) (push event-queue event)) @@ -250,7 +251,7 @@ Usage: (dispatch-sync [:delete-item 42])" - [event-v] - (handle event-v) + [event-queue registry event-v] + (ev/handle registry event-v) (-call-post-event-callbacks event-queue event-v) ;; slightly ugly hack. Run the registered post event callbacks. nil) ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Beware-Returning-False diff --git a/src/re_frame/std_interceptors.cljc b/src/re_frame/std_interceptors.cljc index 6fd8c7f93..82d0c51e6 100644 --- a/src/re_frame/std_interceptors.cljc +++ b/src/re_frame/std_interceptors.cljc @@ -3,7 +3,6 @@ (:require [re-frame.interceptor :refer [->interceptor get-effect get-coeffect assoc-coeffect assoc-effect]] [re-frame.loggers :refer [console]] - [re-frame.registrar :as registrar] [re-frame.db :refer [app-db]] [clojure.data :as data] [re-frame.cofx :as cofx] diff --git a/src/re_frame/subs.cljc b/src/re_frame/subs.cljc index 1f42c6f1a..54f89a0d3 100644 --- a/src/re_frame/subs.cljc +++ b/src/re_frame/subs.cljc @@ -4,11 +4,11 @@ [re-frame.interop :refer [add-on-dispose! debug-enabled? make-reaction ratom? deref? dispose! reagent-id]] [re-frame.loggers :refer [console]] [re-frame.utils :refer [first-in-vector]] - [re-frame.registrar :refer [get-handler clear-handlers register-handler]] + [re-frame.registry :as reg] [re-frame.trace :as trace :include-macros true])) (def kind :sub) -(assert (re-frame.registrar/kinds kind)) +(assert (re-frame.registry/kinds kind)) ;; -- cache ------------------------------------------------------------------- ;; @@ -37,8 +37,8 @@ (defn clear-all-handlers! "Unregisters all existing subscription handlers" - [] - (clear-handlers kind) + [registry] + (reg/clear-handlers registry kind) (clear-subscription-cache!)) (defn cache-and-return @@ -68,7 +68,7 @@ (defn subscribe "Returns a Reagent/reaction which contains a computation" - ([query-v] + ([registry query-v] (trace/with-trace {:operation (first-in-vector query-v) :op-type :sub/create :tags {:query-v query-v}} @@ -79,14 +79,14 @@ cached) (let [query-id (first-in-vector query-v) - handler-fn (get-handler kind query-id)] + handler-fn (reg/get-handler registry kind query-id)] (trace/merge-trace! {:tags {:cached? false}}) (if (nil? handler-fn) (do (trace/merge-trace! {:error true}) (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] + ([registry v dynv] (trace/with-trace {:operation (first-in-vector v) :op-type :sub/create :tags {:query-v v @@ -97,7 +97,7 @@ :reaction (reagent-id cached)}}) cached) (let [query-id (first-in-vector v) - handler-fn (get-handler kind query-id)] + handler-fn (reg/get-handler registry kind query-id)] (trace/merge-trace! {:tags {:cached? false}}) (when debug-enabled? (when-let [not-reactive (not-empty (remove ratom? dynv))] @@ -109,7 +109,7 @@ sub (make-reaction (fn [] (handler-fn app-db v @dyn-vals)))] ;; handler-fn returns a reaction which is then wrapped in the sub reaction ;; need to double deref it to get to the actual value. - ;(console :log "Subscription created: " v dynv) + ;; (console :log "Subscription created: " v dynv) (cache-and-return v dynv (make-reaction (fn [] @@sub)))))))))) ;; -- reg-sub ----------------------------------------------------------------- @@ -166,7 +166,7 @@ of an `input signals` functions. `:<-` is supplied followed by the subscription vector. " - [query-id & args] + [registry query-id & args] (let [computation-fn (last args) input-args (butlast args) ;; may be empty, or one fn, or pairs of :<- / vector err-header (str "re-frame: reg-sub for " query-id ", ") @@ -184,8 +184,8 @@ ;; one sugar pair 2 (fn inp-fn - ([_] (subscribe (second input-args))) - ([_ _] (subscribe (second input-args)))) + ([_] (subscribe registry (second input-args))) + ([_ _] (subscribe registry (second input-args)))) ;; multiple sugar pairs (let [pairs (partition 2 input-args) @@ -193,9 +193,10 @@ (when-not (every? vector? vecs) (console :error err-header "expected pairs of :<- and vectors, got:" pairs)) (fn inp-fn - ([_] (map subscribe vecs)) - ([_ _] (map subscribe vecs)))))] - (register-handler + ([_] (map (partial subscribe registry) vecs)) + ([_ _] (map (partial subscribe registry) vecs)))))] + (reg/register-handler + registry kind query-id (fn subs-handler-fn diff --git a/test/re-frame/restore_test.cljs b/test/re-frame/restore_test.cljs index 5052f068a..a419cd6af 100644 --- a/test/re-frame/restore_test.cljs +++ b/test/re-frame/restore_test.cljs @@ -1,11 +1,11 @@ (ns re-frame.restore-test (:require [cljs.test :refer-macros [is deftest async use-fixtures testing]] - [re-frame.core :refer [make-restore-fn reg-sub subscribe]] + [re-frame.core :as core :refer [make-restore-fn reg-sub subscribe]] [re-frame.subs :as subs])) ;; TODO: future tests in this area could check DB state and registrations are being correctly restored. -(use-fixtures :each {:before subs/clear-all-handlers!}) +(use-fixtures :each {:before (partial subs/clear-all-handlers! core/registry)}) (defn one? [x] (= 1 x)) (defn two? [x] (= 2 x)) diff --git a/test/re-frame/subs_test.cljs b/test/re-frame/subs_test.cljs index 8850a9ee7..2bd24f995 100644 --- a/test/re-frame/subs_test.cljs +++ b/test/re-frame/subs_test.cljs @@ -1,128 +1,147 @@ (ns re-frame.subs-test (:require [cljs.test :as test :refer-macros [is deftest testing]] [reagent.ratom :as r :refer-macros [reaction]] + [re-frame.registry :as reg] [re-frame.subs :as subs] [re-frame.db :as db] [re-frame.core :as re-frame])) -(test/use-fixtures :each {:before (fn [] (subs/clear-all-handlers!))}) +(def registry (atom nil)) -;=====test basic subscriptions ====== +(defn reg-sub-raw + "Associate a given `query id` with a given subscription handler function `handler-fn` + which is expected to take two arguments: app-db and query vector, and return + a `reaction`. + + This is a low level, advanced function. You should probably be using reg-sub + instead." + [query-id handler-fn] + (reg/register-handler @registry subs/kind query-id handler-fn)) + + +(test/use-fixtures :each {:before (fn [] + (reset! registry (reg/make-registry)) + (subs/clear-all-handlers! @registry))}) + +;;=====test basic subscriptions ====== (deftest test-reg-sub - (re-frame/reg-sub-raw - :test-sub - (fn [db [_]] (reaction (deref db)))) + (reg-sub-raw + :test-sub + (fn [db [_]] (reaction (deref db)))) - (let [test-sub (subs/subscribe [:test-sub])] + (let [test-sub (subs/subscribe @registry [:test-sub])] (is (= @db/app-db @test-sub)) (reset! db/app-db 1) (is (= 1 @test-sub)))) (deftest test-chained-subs - (re-frame/reg-sub-raw - :a-sub - (fn [db [_]] (reaction (:a @db)))) - - (re-frame/reg-sub-raw - :b-sub - (fn [db [_]] (reaction (:b @db)))) - - (re-frame/reg-sub-raw - :a-b-sub - (fn [db [_]] - (let [a (subs/subscribe [:a-sub]) - b (subs/subscribe [:b-sub])] - (reaction {:a @a :b @b})))) - - (let [test-sub (subs/subscribe [:a-b-sub])] + (reg-sub-raw + :a-sub + (fn [db [_]] (reaction (:a @db)))) + + (reg-sub-raw + :b-sub + (fn [db [_]] (reaction (:b @db)))) + + (reg-sub-raw + :a-b-sub + (fn [db [_]] + (let [a (subs/subscribe @registry [:a-sub]) + b (subs/subscribe @registry [:b-sub])] + (reaction {:a @a :b @b})))) + + (let [test-sub (subs/subscribe @registry [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) (is (= {:a 1 :b 3} @test-sub)))) (deftest test-sub-parameters - (re-frame/reg-sub-raw - :test-sub - (fn [db [_ b]] (reaction [(:a @db) b]))) + (reg-sub-raw + :test-sub + (fn [db [_ b]] (reaction [(:a @db) b]))) - (let [test-sub (subs/subscribe [:test-sub :c])] + (let [test-sub (subs/subscribe @registry [:test-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= [1 :c] @test-sub)))) (deftest test-sub-chained-parameters - (re-frame/reg-sub-raw - :a-sub - (fn [db [_ a]] (reaction [(:a @db) a]))) - - (re-frame/reg-sub-raw - :b-sub - (fn [db [_ b]] (reaction [(:b @db) b]))) - - (re-frame/reg-sub-raw - :a-b-sub - (fn [db [_ c]] - (let [a (subs/subscribe [:a-sub c]) - b (subs/subscribe [:b-sub c])] - (reaction {:a @a :b @b})))) - - (let [test-sub (subs/subscribe [:a-b-sub :c])] + (reg-sub-raw + :a-sub + (fn [db [_ a]] (reaction [(:a @db) a]))) + + (reg-sub-raw + :b-sub + (fn [db [_ b]] (reaction [(:b @db) b]))) + + (reg-sub-raw + :a-b-sub + (fn [db [_ c]] + (let [a (subs/subscribe @registry [:a-sub c]) + b (subs/subscribe @registry [:b-sub c])] + (reaction {:a @a :b @b})))) + + (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a [1 :c], :b [2 :c]} @test-sub)))) (deftest test-nonexistent-sub - (is (nil? (re-frame/subscribe [:non-existence])))) + (is (nil? (subs/subscribe @registry [:non-existence])))) -;============== test cached-subs ================ +;;============== test cached-subs ================ (def side-effect-atom (atom 0)) (deftest test-cached-subscriptions (reset! side-effect-atom 0) - (re-frame/reg-sub-raw - :side-effecting-handler - (fn side-effect - [db [_] [_]] - (swap! side-effect-atom inc) - (reaction @db))) + (reg-sub-raw + :side-effecting-handler + (fn side-effect + [db [_] [_]] + (swap! side-effect-atom inc) + (reaction @db))) - (let [test-sub (subs/subscribe [:side-effecting-handler])] + (let [test-sub (subs/subscribe @registry [:side-effecting-handler])] (reset! db/app-db :test) (is (= :test @test-sub)) (is (= @side-effect-atom 1)) - (subs/subscribe [:side-effecting-handler]) ;; this should be handled by cache + (subs/subscribe @registry [:side-effecting-handler]) ;; this should be handled by cache (is (= @side-effect-atom 1)) - (subs/subscribe [:side-effecting-handler :a]) ;; should fire again because of the param + (subs/subscribe @registry [:side-effecting-handler :a]) ;; should fire again because of the param (is (= @side-effect-atom 2)) - (subs/subscribe [:side-effecting-handler :a]) ;; this should be handled by cache + (subs/subscribe @registry [:side-effecting-handler :a]) ;; this should be handled by cache (is (= @side-effect-atom 2)))) -;============== test register-pure macros ================ +;;============== test register-pure macros ================ (deftest test-reg-sub-macro (subs/reg-sub - :test-sub - (fn [db [_]] db)) + @registry + :test-sub + (fn [db [_]] db)) - (let [test-sub (subs/subscribe [:test-sub])] + (let [test-sub (subs/subscribe @registry [:test-sub])] (is (= @db/app-db @test-sub)) (reset! db/app-db 1) (is (= 1 @test-sub)))) (deftest test-reg-sub-macro-singleton (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :a-b-sub - (fn [_ _ _] - (subs/subscribe [:a-sub])) - (fn [a [_]] - {:a a})) - - (let [test-sub (subs/subscribe [:a-b-sub])] + @registry + :a-b-sub + (fn [_ _ _] + (subs/subscribe @registry [:a-sub])) + (fn [a [_]] + {:a a})) + + (let [test-sub (subs/subscribe @registry [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1} @test-sub)) (swap! db/app-db assoc :b 3) @@ -130,22 +149,25 @@ (deftest test-reg-sub-macro-vector (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :b-sub - (fn [db [_]] (:b db))) + @registry + :b-sub + (fn [db [_]] (:b db))) (subs/reg-sub - :a-b-sub - (fn [_ _ _] - [(subs/subscribe [:a-sub]) - (subs/subscribe [:b-sub])]) - (fn [[a b] [_]] - {:a a :b b})) - - (let [test-sub (subs/subscribe [:a-b-sub])] + @registry + :a-b-sub + (fn [_ _ _] + [(subs/subscribe @registry [:a-sub]) + (subs/subscribe @registry [:b-sub])]) + (fn [[a b] [_]] + {:a a :b b})) + + (let [test-sub (subs/subscribe @registry [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) @@ -153,22 +175,25 @@ (deftest test-reg-sub-macro-map (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :b-sub - (fn [db [_]] (:b db))) + @registry + :b-sub + (fn [db [_]] (:b db))) (subs/reg-sub - :a-b-sub - (fn [_ _ _] - {:a (subs/subscribe [:a-sub]) - :b (subs/subscribe [:b-sub])}) - (fn [{:keys [a b]} [_]] - {:a a :b b})) - - (let [test-sub (subs/subscribe [:a-b-sub])] + @registry + :a-b-sub + (fn [_ _ _] + {:a (subs/subscribe @registry [:a-sub]) + :b (subs/subscribe @registry [:b-sub])}) + (fn [{:keys [a b]} [_]] + {:a a :b b})) + + (let [test-sub (subs/subscribe @registry [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) @@ -176,65 +201,74 @@ (deftest test-sub-macro-parameters (subs/reg-sub - :test-sub - (fn [db [_ b]] [(:a db) b])) + @registry + :test-sub + (fn [db [_ b]] [(:a db) b])) - (let [test-sub (subs/subscribe [:test-sub :c])] + (let [test-sub (subs/subscribe @registry [:test-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= [1 :c] @test-sub)))) (deftest test-sub-macros-chained-parameters (subs/reg-sub - :a-sub - (fn [db [_ a]] [(:a db) a])) + @registry + :a-sub + (fn [db [_ a]] [(:a db) a])) (subs/reg-sub - :b-sub - (fn [db [_ b]] [(:b db) b])) + @registry + :b-sub + (fn [db [_ b]] [(:b db) b])) (subs/reg-sub - :a-b-sub - (fn [[_ c] _] - [(subs/subscribe [:a-sub c]) - (subs/subscribe [:b-sub c])]) - (fn [[a b] [_ c]] {:a a :b b})) - - (let [test-sub (subs/subscribe [:a-b-sub :c])] + @registry + :a-b-sub + (fn [[_ c] _] + [(subs/subscribe @registry [:a-sub c]) + (subs/subscribe @registry [:b-sub c])]) + (fn [[a b] [_ c]] {:a a :b b})) + + (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a [1 :c] :b [2 :c]} @test-sub)))) (deftest test-sub-macros-<- "test the syntactial sugar" (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :a-b-sub - :<- [:a-sub] - (fn [a [_]] {:a a})) + @registry + :a-b-sub + :<- [:a-sub] + (fn [a [_]] {:a a})) - (let [test-sub (subs/subscribe [:a-b-sub])] + (let [test-sub (subs/subscribe @registry [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1} @test-sub)))) (deftest test-sub-macros-chained-parameters-<- "test the syntactial sugar" (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :b-sub - (fn [db [_]] (:b db))) + @registry + :b-sub + (fn [db [_]] (:b db))) (subs/reg-sub - :a-b-sub - :<- [:a-sub] - :<- [:b-sub] - (fn [[a b] [_ c]] {:a a :b b})) + @registry + :a-b-sub + :<- [:a-sub] + :<- [:b-sub] + (fn [[a b] [_ c]] {:a a :b b})) - (let [test-sub (subs/subscribe [:a-b-sub :c])] + (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub) ))) @@ -242,30 +276,35 @@ (let [sub-called? (atom false)] (with-redefs [subs/subscribe (fn [& args] (reset! sub-called? true))] (subs/reg-sub - :a-sub - (fn [db [_]] (:a db))) + @registry + :a-sub + (fn [db [_]] (:a db))) (subs/reg-sub - :b-sub - (fn [db [_]] (:b db))) + @registry + :b-sub + (fn [db [_]] (:b db))) (subs/reg-sub - :fn-sub - (fn [[_ c] _] - [(subs/subscribe [:a-sub c]) - (subs/subscribe [:b-sub c])]) - (fn [db [_]] (:b db))) + @registry + :fn-sub + (fn [[_ c] _] + [(subs/subscribe @registry [:a-sub c]) + (subs/subscribe @registry [:b-sub c])]) + (fn [db [_]] (:b db))) (subs/reg-sub - :a-sugar-sub - :<- [:a-sub] - (fn [[a] [_ c]] {:a a})) + @registry + :a-sugar-sub + :<- [:a-sub] + (fn [[a] [_ c]] {:a a})) (subs/reg-sub - :a-b-sub - :<- [:a-sub] - :<- [:b-sub] - (fn [[a b] [_ c]] {:a a :b b}))) + @registry + :a-b-sub + :<- [:a-sub] + :<- [:b-sub] + (fn [[a b] [_ c]] {:a a :b b}))) (is (false? @sub-called?)))) @@ -273,13 +312,14 @@ (deftest test-dynamic-subscriptions (subs/reg-sub + @registry :dyn-sub (fn [db ev dynv] (first dynv))) (testing "happy case" - (is (= 1 @(subs/subscribe [:dyn-sub] [(r/atom 1)])))) + (is (= 1 @(subs/subscribe @registry [:dyn-sub] [(r/atom 1)])))) (testing "subscription that doesn't exist" - (is (nil? (subs/subscribe [:non-existent] [(r/atom 1)])))) + (is (nil? (subs/subscribe @registry [:non-existent] [(r/atom 1)])))) (testing "Passing a non-reactive value to a dynamic subscription" - (is (thrown-with-msg? js/Error #"No protocol method IDeref" @(subs/subscribe [:dyn-sub] [1]))))) + (is (thrown-with-msg? js/Error #"No protocol method IDeref" @(subs/subscribe @registry [:dyn-sub] [1]))))) From af1c112cffc90b210b69b9f11d3e5aec17212290 Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Mon, 19 Dec 2016 19:10:11 +0800 Subject: [PATCH 30/33] make make-restore-fn use core/registry --- src/re_frame/core.cljc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/re_frame/core.cljc b/src/re_frame/core.cljc index 3638be4ff..6f1e04c7e 100644 --- a/src/re_frame/core.cljc +++ b/src/re_frame/core.cljc @@ -138,12 +138,12 @@ Checkpoint includes app-db, all registered handlers and all subscriptions. " [] - (let [handlers @registrar/kind->id->handler + (let [handlers (-> registry :kind->id->handler deref) app-db @db/app-db - subs-cache @subs/query->reaction] + subs-cache @subs/query->reaction] (fn [] - ;; call `dispose!` on all current subscriptions which - ;; didn't originally exist. + ;; call `dispose!` on all current subscriptions which + ;; didn't originally exist. (let [original-subs (set (vals subs-cache)) current-subs (set (vals @subs/query->reaction))] (doseq [sub (set/difference current-subs original-subs)] @@ -152,7 +152,7 @@ ;; Reset the atoms ;; We don't need to reset subs/query->reaction, as ;; disposing of the subs removes them from the cache anyway - (reset! registrar/kind->id->handler handlers) + (reset! (:kind->id->handler registry) handlers) (reset! db/app-db app-db) nil))) From ab732f1b8f2bd43edab4dfad47a89d84dfb7d61d Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Tue, 20 Dec 2016 03:11:48 +0800 Subject: [PATCH 31/33] turn public API into protocol and singleton in re-frame.core --- src/re_frame/cofx.cljc | 2 +- src/re_frame/core.cljc | 118 +++++++++++------------------- src/re_frame/frame.cljc | 112 +++++++++++++++++++++++++++++ src/re_frame/fx.cljc | 2 +- src/re_frame/subs.cljc | 14 ++-- test/re-frame/restore_test.cljs | 2 +- test/re-frame/subs_test.cljs | 122 ++++++++++++++++---------------- 7 files changed, 224 insertions(+), 148 deletions(-) create mode 100644 src/re_frame/frame.cljc diff --git a/src/re_frame/cofx.cljc b/src/re_frame/cofx.cljc index b37adeb0f..87b735e04 100644 --- a/src/re_frame/cofx.cljc +++ b/src/re_frame/cofx.cljc @@ -52,7 +52,7 @@ ;; -- Builtin CoEffects Handlers --------------------------------------------- (defn register-built-in! - [registry] + [{:keys [app-db registry] :as frame}] (let [register (partial reg/register-handler registry kind)] (register :db diff --git a/src/re_frame/core.cljc b/src/re_frame/core.cljc index 6f1e04c7e..783bc1b62 100644 --- a/src/re_frame/core.cljc +++ b/src/re_frame/core.cljc @@ -2,34 +2,20 @@ (:require [re-frame.events :as events] [re-frame.subs :as subs] + [re-frame.frame :as frame] [re-frame.interop :as interop] [re-frame.db :as db] [re-frame.fx :as fx] [re-frame.cofx :as cofx] [re-frame.router :as router] [re-frame.loggers :as loggers] - [re-frame.registrar :as registrar] [re-frame.registry :as reg] [re-frame.interceptor :as interceptor] [re-frame.std-interceptors :as std-interceptors :refer [db-handler->interceptor - fx-handler->interceptor - ctx-handler->interceptor]] + fx-handler->interceptor + ctx-handler->interceptor]] [clojure.set :as set])) - -;; -- state -(def registry (reg/make-registry)) -(def ev-queue (router/->EventQueue :idle interop/empty-queue {} registry)) - -;; -- dispatch -(def dispatch (partial router/dispatch ev-queue)) -(def dispatch-sync (partial router/dispatch-sync ev-queue registry)) - - -;; XXX move API functions up to this core level - to enable code completion and docs -;; XXX on figwheel reload, is there a way to not get the re-registration messages. - - ;; -- interceptor related ;; useful if you are writing your own interceptors (def ->interceptor interceptor/->interceptor) @@ -48,69 +34,47 @@ (def after std-interceptors/after) (def on-changes std-interceptors/on-changes) +;; XXX move API functions up to this core level - to enable code completion and docs +;; XXX on figwheel reload, is there a way to not get the re-registration messages. -;; -- subscriptions -(defn reg-sub-raw - "Associate a given `query id` with a given subscription handler function `handler-fn` - which is expected to take two arguments: app-db and query vector, and return - a `reaction`. - - This is a low level, advanced function. You should probably be using reg-sub - instead." - [query-id handler-fn] - (reg/register-handler registry subs/kind query-id handler-fn)) - -(def reg-sub (partial subs/reg-sub registry)) -(def subscribe (partial subs/subscribe registry)) - -(def clear-sub (partial reg/clear-handlers registry subs/kind)) -(def clear-subscription-cache! subs/clear-subscription-cache!) - -;; -- effects -(def reg-fx (partial reg/register-handler registry fx/kind)) -(def clear-fx (partial reg/clear-handlers registry fx/kind)) -(def fx-do-fx (fx/do-fx registry)) -(fx/register-built-in! registry ev-queue) - -;; -- coeffects -(def reg-cofx (partial reg/register-handler registry cofx/kind)) -(def inject-cofx (partial cofx/inject-cofx registry)) -(def clear-cofx (partial reg/clear-handlers registry cofx/kind)) -(def cofx-inject-db (cofx/inject-cofx registry :db)) -(cofx/register-built-in! registry) +;; Export API wrapping `the-frame` singleton --- +(defn make-frame [] + (let [registry (reg/make-registry) + event-queue (router/->EventQueue :idle interop/empty-queue {} registry)] + (frame/map->Frame + {:registry registry + :event-queue event-queue + :app-db re-frame.db/app-db + :subscriptions-cache nil}))) -;; -- Events -(def clear-event (partial reg/clear-handlers registry events/kind)) +(def the-frame (make-frame)) -(defn reg-event-db - "Register the given `id`, typically a keyword, with the combination of - `db-handler` and an interceptor chain. - `db-handler` is a function: (db event) -> db - `interceptors` is a collection of interceptors, possibly nested (needs flattening). - `db-handler` is wrapped in an interceptor and added to the end of the chain, so in the end - there is only a chain. - The necessary effects and coeffects handler are added to the front of the - interceptor chain. These interceptors ensure that app-db is available and updated." - ([id db-handler] - (reg-event-db id nil db-handler)) - ([id interceptors db-handler] - (events/register registry id [cofx-inject-db fx-do-fx interceptors (db-handler->interceptor db-handler)]))) +(fx/register-built-in! the-frame) +(cofx/register-built-in! the-frame) +(def dispatch (partial frame/dispatch the-frame)) +(def dispatch-sync (partial frame/dispatch-sync the-frame)) -(defn reg-event-fx - ([id fx-handler] - (reg-event-fx id nil fx-handler)) - ([id interceptors fx-handler] - (events/register registry id [cofx-inject-db fx-do-fx interceptors (fx-handler->interceptor fx-handler)]))) +(def reg-sub-raw (partial frame/reg-sub-raw the-frame)) +;; some slight weirdness here because protocols don't support variadic functions +(defn reg-sub [query-id & args] + (frame/reg-sub the-frame query-id args)) +(def subscribe (partial frame/subscribe the-frame)) +(def clear-sub (partial frame/clear-sub the-frame)) +(def clear-subscriptions-cache! (partial frame/clear-subscriptions-cache the-frame)) +(def reg-fx (partial frame/reg-fx the-frame)) +(def clear-fx (partial frame/clear-fx the-frame)) -(defn reg-event-ctx - ([id handler] - (reg-event-ctx id nil handler)) - ([id interceptors handler] - (events/register registry id [cofx-inject-db fx-do-fx interceptors (ctx-handler->interceptor handler)]))) +(def reg-cofx (partial frame/reg-cofx the-frame)) +(def inject-cofx (partial frame/inject-cofx the-frame)) +(def clear-cofx (partial frame/clear-cofx the-frame)) +(def reg-event-db (partial frame/reg-event-db the-frame)) +(def reg-event-fx (partial frame/reg-event-fx the-frame)) +(def reg-event-ctx (partial frame/reg-event-ctx the-frame)) +(def clear-event (partial frame/clear-event the-frame)) ;; -- Logging ----- ;; Internally, re-frame uses the logging functions: warn, log, error, group and groupEnd @@ -138,8 +102,8 @@ Checkpoint includes app-db, all registered handlers and all subscriptions. " [] - (let [handlers (-> registry :kind->id->handler deref) - app-db @db/app-db + (let [handlers (-> the-frame :registry :kind->id->handler deref) + app-db (-> the-frame :app-db deref) subs-cache @subs/query->reaction] (fn [] ;; call `dispose!` on all current subscriptions which @@ -152,8 +116,8 @@ ;; Reset the atoms ;; We don't need to reset subs/query->reaction, as ;; disposing of the subs removes them from the cache anyway - (reset! (:kind->id->handler registry) handlers) - (reset! db/app-db app-db) + (reset! (-> the-frame :registry :kind->id->handler) handlers) + (reset! (-> the-frame :app-db) app-db) nil))) @@ -177,12 +141,12 @@ ([f] (add-post-event-callback f f)) ;; use f as its own identifier ([id f] - (router/add-post-event-callback ev-queue id f))) + (router/add-post-event-callback (:event-queue the-frame) id f))) (defn remove-post-event-callback [id] - (router/remove-post-event-callback ev-queue id)) + (router/remove-post-event-callback (:event-queue the-frame) id)) ;; -- Deprecation Messages diff --git a/src/re_frame/frame.cljc b/src/re_frame/frame.cljc new file mode 100644 index 000000000..2af801ba7 --- /dev/null +++ b/src/re_frame/frame.cljc @@ -0,0 +1,112 @@ +(ns re-frame.frame + (:require + [re-frame.events :as events] + [re-frame.subs :as subs] + [re-frame.events :as events] + [re-frame.fx :as fx] + [re-frame.cofx :as cofx] + [re-frame.router :as router] + [re-frame.registry :as reg] + [re-frame.std-interceptors :as stdi])) + +(defprotocol IFrame + ;; dispatch ---- + (dispatch [this event-v]) + (dispatch-sync [this event-v]) + + ;; subs ---- + (reg-sub-raw [this query-id handler-fn]) + (reg-sub [this query-id args]) + (subscribe + [this query-v] + [this query-v dyn-v]) + (clear-sub [this query-id]) + (clear-subscriptions-cache [this]) + + ;; fx ---- + (reg-fx [this fx-id handler-fn]) + (clear-fx [this fx-id]) + + ;; cofx ---- + (reg-cofx [this cofx-id handler-fn]) + (inject-cofx + [this cofx-id] + [this cofx-id value]) + (clear-cofx [this cofx-id]) + + ;; events ---- + (clear-event [this event-id]) + (reg-event-db + [this id db-handler] + [this id interceptors db-handler]) + (reg-event-fx + [this id fx-handler] + [this id interceptors fx-handler]) + (reg-event-ctx + [this id handler] + [this id interceptors handler])) + +;; connect all the pieces of state ---- +(defrecord Frame [registry event-queue app-db subscriptions-cache] + IFrame + ;; dispatch ---- + (dispatch [this event-v] + (router/dispatch event-queue event-v)) + (dispatch-sync [this event-v] + (router/dispatch-sync event-queue registry event-v)) + + ;; subs ---- + (reg-sub-raw [this query-id handler-fn] + (reg/register-handler registry subs/kind query-id handler-fn)) + (reg-sub [this query-id args] + (apply subs/reg-sub this query-id args)) + (subscribe [this query-v] + (subs/subscribe this query-v)) + (subscribe [this query-v dyn-v] + (subs/subscribe this query-v dyn-v)) + (clear-sub [this query-id] + (reg/clear-handlers registry subs/kind query-id)) + (clear-subscriptions-cache [this] + (subs/clear-subscription-cache!)) + + ;; fx ---- + (reg-fx [this fx-id handler-fn] + (reg/register-handler registry fx/kind fx-id handler-fn)) + (clear-fx [this fx-id] + (reg/clear-handlers registry fx/kind fx-id)) + + ;; cofx ---- + (reg-cofx [this cofx-id handler-fn] + (reg/register-handler registry cofx/kind cofx-id handler-fn)) + (inject-cofx [this cofx-id] + (cofx/inject-cofx registry cofx-id)) + (inject-cofx [this cofx-id value] + (cofx/inject-cofx registry cofx-id value)) + (clear-cofx [this cofx-id] + (reg/clear-handlers registry cofx/kind cofx-id)) + + ;; events ---- + (clear-event [this id] + (reg/clear-handlers registry events/kind id)) + + (reg-event-db [this id db-handler] + (reg-event-db this id nil db-handler)) + (reg-event-db [this id interceptors db-handler] + (events/register + registry + id + [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/db-handler->interceptor db-handler)])) + (reg-event-fx [this id fx-handler] + (reg-event-fx this id nil fx-handler)) + (reg-event-fx [this id interceptors fx-handler] + (events/register + registry + id + [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/fx-handler->interceptor fx-handler)])) + (reg-event-ctx [this id handler] + (reg-event-ctx this id nil handler)) + (reg-event-ctx [this id interceptors handler] + (events/register + registry + id + [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/ctx-handler->interceptor handler)]))) diff --git a/src/re_frame/fx.cljc b/src/re_frame/fx.cljc index 57e389957..d2ac3a7ef 100644 --- a/src/re_frame/fx.cljc +++ b/src/re_frame/fx.cljc @@ -41,7 +41,7 @@ ;; -- Builtin Effect Handlers ------------------------------------------------ (defn register-built-in! - [registry event-queue] + [{:keys [registry app-db event-queue] :as frame}] (let [register (partial reg/register-handler registry kind)] ;; :dispatch-later diff --git a/src/re_frame/subs.cljc b/src/re_frame/subs.cljc index 54f89a0d3..c226df965 100644 --- a/src/re_frame/subs.cljc +++ b/src/re_frame/subs.cljc @@ -68,7 +68,7 @@ (defn subscribe "Returns a Reagent/reaction which contains a computation" - ([registry query-v] + ([{:keys [registry app-db]} query-v] (trace/with-trace {:operation (first-in-vector query-v) :op-type :sub/create :tags {:query-v query-v}} @@ -86,7 +86,7 @@ (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))))))) - ([registry v dynv] + ([{:keys [registry app-db]} v dynv] (trace/with-trace {:operation (first-in-vector v) :op-type :sub/create :tags {:query-v v @@ -166,7 +166,7 @@ of an `input signals` functions. `:<-` is supplied followed by the subscription vector. " - [registry query-id & args] + [{:keys [registry app-db] :as frame} query-id & args] (let [computation-fn (last args) input-args (butlast args) ;; may be empty, or one fn, or pairs of :<- / vector err-header (str "re-frame: reg-sub for " query-id ", ") @@ -184,8 +184,8 @@ ;; one sugar pair 2 (fn inp-fn - ([_] (subscribe registry (second input-args))) - ([_ _] (subscribe registry (second input-args)))) + ([_] (subscribe frame (second input-args))) + ([_ _] (subscribe frame (second input-args)))) ;; multiple sugar pairs (let [pairs (partition 2 input-args) @@ -193,8 +193,8 @@ (when-not (every? vector? vecs) (console :error err-header "expected pairs of :<- and vectors, got:" pairs)) (fn inp-fn - ([_] (map (partial subscribe registry) vecs)) - ([_ _] (map (partial subscribe registry) vecs)))))] + ([_] (map (partial subscribe frame) vecs)) + ([_ _] (map (partial subscribe frame) vecs)))))] (reg/register-handler registry kind diff --git a/test/re-frame/restore_test.cljs b/test/re-frame/restore_test.cljs index a419cd6af..8b2437477 100644 --- a/test/re-frame/restore_test.cljs +++ b/test/re-frame/restore_test.cljs @@ -5,7 +5,7 @@ ;; TODO: future tests in this area could check DB state and registrations are being correctly restored. -(use-fixtures :each {:before (partial subs/clear-all-handlers! core/registry)}) +(use-fixtures :each {:before (partial subs/clear-all-handlers! (:registry core/the-frame))}) (defn one? [x] (= 1 x)) (defn two? [x] (= 2 x)) diff --git a/test/re-frame/subs_test.cljs b/test/re-frame/subs_test.cljs index 2bd24f995..46031a263 100644 --- a/test/re-frame/subs_test.cljs +++ b/test/re-frame/subs_test.cljs @@ -6,7 +6,7 @@ [re-frame.db :as db] [re-frame.core :as re-frame])) -(def registry (atom nil)) +(def frame (atom nil)) (defn reg-sub-raw "Associate a given `query id` with a given subscription handler function `handler-fn` @@ -16,12 +16,12 @@ This is a low level, advanced function. You should probably be using reg-sub instead." [query-id handler-fn] - (reg/register-handler @registry subs/kind query-id handler-fn)) + (reg/register-handler (:registry @frame) subs/kind query-id handler-fn)) (test/use-fixtures :each {:before (fn [] - (reset! registry (reg/make-registry)) - (subs/clear-all-handlers! @registry))}) + (reset! frame (re-frame/make-frame)) + (subs/clear-all-handlers! (:registry @frame)))}) ;;=====test basic subscriptions ====== @@ -30,7 +30,7 @@ :test-sub (fn [db [_]] (reaction (deref db)))) - (let [test-sub (subs/subscribe @registry [:test-sub])] + (let [test-sub (subs/subscribe @frame [:test-sub])] (is (= @db/app-db @test-sub)) (reset! db/app-db 1) (is (= 1 @test-sub)))) @@ -47,11 +47,11 @@ (reg-sub-raw :a-b-sub (fn [db [_]] - (let [a (subs/subscribe @registry [:a-sub]) - b (subs/subscribe @registry [:b-sub])] + (let [a (subs/subscribe @frame [:a-sub]) + b (subs/subscribe @frame [:b-sub])] (reaction {:a @a :b @b})))) - (let [test-sub (subs/subscribe @registry [:a-b-sub])] + (let [test-sub (subs/subscribe @frame [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) @@ -62,7 +62,7 @@ :test-sub (fn [db [_ b]] (reaction [(:a @db) b]))) - (let [test-sub (subs/subscribe @registry [:test-sub :c])] + (let [test-sub (subs/subscribe @frame [:test-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= [1 :c] @test-sub)))) @@ -79,16 +79,16 @@ (reg-sub-raw :a-b-sub (fn [db [_ c]] - (let [a (subs/subscribe @registry [:a-sub c]) - b (subs/subscribe @registry [:b-sub c])] + (let [a (subs/subscribe @frame [:a-sub c]) + b (subs/subscribe @frame [:b-sub c])] (reaction {:a @a :b @b})))) - (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] + (let [test-sub (subs/subscribe @frame [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a [1 :c], :b [2 :c]} @test-sub)))) (deftest test-nonexistent-sub - (is (nil? (subs/subscribe @registry [:non-existence])))) + (is (nil? (subs/subscribe @frame [:non-existence])))) ;;============== test cached-subs ================ (def side-effect-atom (atom 0)) @@ -103,45 +103,45 @@ (swap! side-effect-atom inc) (reaction @db))) - (let [test-sub (subs/subscribe @registry [:side-effecting-handler])] + (let [test-sub (subs/subscribe @frame [:side-effecting-handler])] (reset! db/app-db :test) (is (= :test @test-sub)) (is (= @side-effect-atom 1)) - (subs/subscribe @registry [:side-effecting-handler]) ;; this should be handled by cache + (subs/subscribe @frame [:side-effecting-handler]) ;; this should be handled by cache (is (= @side-effect-atom 1)) - (subs/subscribe @registry [:side-effecting-handler :a]) ;; should fire again because of the param + (subs/subscribe @frame [:side-effecting-handler :a]) ;; should fire again because of the param (is (= @side-effect-atom 2)) - (subs/subscribe @registry [:side-effecting-handler :a]) ;; this should be handled by cache + (subs/subscribe @frame [:side-effecting-handler :a]) ;; this should be handled by cache (is (= @side-effect-atom 2)))) ;;============== test register-pure macros ================ (deftest test-reg-sub-macro (subs/reg-sub - @registry + @frame :test-sub (fn [db [_]] db)) - (let [test-sub (subs/subscribe @registry [:test-sub])] + (let [test-sub (subs/subscribe @frame [:test-sub])] (is (= @db/app-db @test-sub)) (reset! db/app-db 1) (is (= 1 @test-sub)))) (deftest test-reg-sub-macro-singleton (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :a-b-sub (fn [_ _ _] - (subs/subscribe @registry [:a-sub])) + (subs/subscribe @frame [:a-sub])) (fn [a [_]] {:a a})) - (let [test-sub (subs/subscribe @registry [:a-b-sub])] + (let [test-sub (subs/subscribe @frame [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1} @test-sub)) (swap! db/app-db assoc :b 3) @@ -149,25 +149,25 @@ (deftest test-reg-sub-macro-vector (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :b-sub (fn [db [_]] (:b db))) (subs/reg-sub - @registry + @frame :a-b-sub (fn [_ _ _] - [(subs/subscribe @registry [:a-sub]) - (subs/subscribe @registry [:b-sub])]) + [(subs/subscribe @frame [:a-sub]) + (subs/subscribe @frame [:b-sub])]) (fn [[a b] [_]] {:a a :b b})) - (let [test-sub (subs/subscribe @registry [:a-b-sub])] + (let [test-sub (subs/subscribe @frame [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) @@ -175,25 +175,25 @@ (deftest test-reg-sub-macro-map (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :b-sub (fn [db [_]] (:b db))) (subs/reg-sub - @registry + @frame :a-b-sub (fn [_ _ _] - {:a (subs/subscribe @registry [:a-sub]) - :b (subs/subscribe @registry [:b-sub])}) + {:a (subs/subscribe @frame [:a-sub]) + :b (subs/subscribe @frame [:b-sub])}) (fn [{:keys [a b]} [_]] {:a a :b b})) - (let [test-sub (subs/subscribe @registry [:a-b-sub])] + (let [test-sub (subs/subscribe @frame [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub)) (swap! db/app-db assoc :b 3) @@ -201,74 +201,74 @@ (deftest test-sub-macro-parameters (subs/reg-sub - @registry + @frame :test-sub (fn [db [_ b]] [(:a db) b])) - (let [test-sub (subs/subscribe @registry [:test-sub :c])] + (let [test-sub (subs/subscribe @frame [:test-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= [1 :c] @test-sub)))) (deftest test-sub-macros-chained-parameters (subs/reg-sub - @registry + @frame :a-sub (fn [db [_ a]] [(:a db) a])) (subs/reg-sub - @registry + @frame :b-sub (fn [db [_ b]] [(:b db) b])) (subs/reg-sub - @registry + @frame :a-b-sub (fn [[_ c] _] - [(subs/subscribe @registry [:a-sub c]) - (subs/subscribe @registry [:b-sub c])]) + [(subs/subscribe @frame [:a-sub c]) + (subs/subscribe @frame [:b-sub c])]) (fn [[a b] [_ c]] {:a a :b b})) - (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] + (let [test-sub (subs/subscribe @frame [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a [1 :c] :b [2 :c]} @test-sub)))) (deftest test-sub-macros-<- "test the syntactial sugar" (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :a-b-sub :<- [:a-sub] (fn [a [_]] {:a a})) - (let [test-sub (subs/subscribe @registry [:a-b-sub])] + (let [test-sub (subs/subscribe @frame [:a-b-sub])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1} @test-sub)))) (deftest test-sub-macros-chained-parameters-<- "test the syntactial sugar" (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :b-sub (fn [db [_]] (:b db))) (subs/reg-sub - @registry + @frame :a-b-sub :<- [:a-sub] :<- [:b-sub] (fn [[a b] [_ c]] {:a a :b b})) - (let [test-sub (subs/subscribe @registry [:a-b-sub :c])] + (let [test-sub (subs/subscribe @frame [:a-b-sub :c])] (reset! db/app-db {:a 1 :b 2}) (is (= {:a 1 :b 2} @test-sub) ))) @@ -276,31 +276,31 @@ (let [sub-called? (atom false)] (with-redefs [subs/subscribe (fn [& args] (reset! sub-called? true))] (subs/reg-sub - @registry + @frame :a-sub (fn [db [_]] (:a db))) (subs/reg-sub - @registry + @frame :b-sub (fn [db [_]] (:b db))) (subs/reg-sub - @registry + @frame :fn-sub (fn [[_ c] _] - [(subs/subscribe @registry [:a-sub c]) - (subs/subscribe @registry [:b-sub c])]) + [(subs/subscribe @frame [:a-sub c]) + (subs/subscribe @frame [:b-sub c])]) (fn [db [_]] (:b db))) (subs/reg-sub - @registry + @frame :a-sugar-sub :<- [:a-sub] (fn [[a] [_ c]] {:a a})) (subs/reg-sub - @registry + @frame :a-b-sub :<- [:a-sub] :<- [:b-sub] @@ -312,14 +312,14 @@ (deftest test-dynamic-subscriptions (subs/reg-sub - @registry + @frame :dyn-sub (fn [db ev dynv] (first dynv))) (testing "happy case" - (is (= 1 @(subs/subscribe @registry [:dyn-sub] [(r/atom 1)])))) + (is (= 1 @(subs/subscribe @frame [:dyn-sub] [(r/atom 1)])))) (testing "subscription that doesn't exist" - (is (nil? (subs/subscribe @registry [:non-existent] [(r/atom 1)])))) + (is (nil? (subs/subscribe @frame [:non-existent] [(r/atom 1)])))) (testing "Passing a non-reactive value to a dynamic subscription" - (is (thrown-with-msg? js/Error #"No protocol method IDeref" @(subs/subscribe @registry [:dyn-sub] [1]))))) + (is (thrown-with-msg? js/Error #"No protocol method IDeref" @(subs/subscribe @frame [:dyn-sub] [1]))))) \ No newline at end of file From b897a4d9b311a3f5483ccac2baffdd58bfb6933a Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Tue, 20 Dec 2016 16:06:40 +0800 Subject: [PATCH 32/33] refactor subs-cache; integrate into frame singleton --- src/re_frame/core.cljc | 21 ++++---- src/re_frame/frame.cljc | 4 +- src/re_frame/subs.cljc | 95 +++++++++++++++++++-------------- test/re-frame/restore_test.cljs | 34 ++++++------ test/re-frame/subs_test.cljs | 2 +- 5 files changed, 87 insertions(+), 69 deletions(-) diff --git a/src/re_frame/core.cljc b/src/re_frame/core.cljc index 783bc1b62..5e7386d7d 100644 --- a/src/re_frame/core.cljc +++ b/src/re_frame/core.cljc @@ -41,12 +41,13 @@ (defn make-frame [] (let [registry (reg/make-registry) - event-queue (router/->EventQueue :idle interop/empty-queue {} registry)] + event-queue (router/->EventQueue :idle interop/empty-queue {} registry) + subs-cache (subs/->SubscriptionCache (atom {}))] (frame/map->Frame {:registry registry :event-queue event-queue :app-db re-frame.db/app-db - :subscriptions-cache nil}))) + :subs-cache subs-cache}))) (def the-frame (make-frame)) @@ -62,7 +63,7 @@ (frame/reg-sub the-frame query-id args)) (def subscribe (partial frame/subscribe the-frame)) (def clear-sub (partial frame/clear-sub the-frame)) -(def clear-subscriptions-cache! (partial frame/clear-subscriptions-cache the-frame)) +(def clear-subscriptions-cache! (partial subs/-clear (:subs-cache the-frame))) (def reg-fx (partial frame/reg-fx the-frame)) (def clear-fx (partial frame/clear-fx the-frame)) @@ -102,20 +103,20 @@ Checkpoint includes app-db, all registered handlers and all subscriptions. " [] - (let [handlers (-> the-frame :registry :kind->id->handler deref) - app-db (-> the-frame :app-db deref) - subs-cache @subs/query->reaction] + (let [handlers (-> the-frame :registry :kind->id->handler deref) + app-db (-> the-frame :app-db deref) + subs-cache (-> the-frame :subs-cache deref)] (fn [] ;; call `dispose!` on all current subscriptions which ;; didn't originally exist. - (let [original-subs (set (vals subs-cache)) - current-subs (set (vals @subs/query->reaction))] + (let [original-subs (-> subs-cache vals set) + current-subs (-> the-frame :subs-cache deref vals set)] (doseq [sub (set/difference current-subs original-subs)] (interop/dispose! sub))) ;; Reset the atoms - ;; We don't need to reset subs/query->reaction, as - ;; disposing of the subs removes them from the cache anyway + ;; We don't need to reset subs-cache, as disposing of the subs + ;; removes them from the cache anyway (reset! (-> the-frame :registry :kind->id->handler) handlers) (reset! (-> the-frame :app-db) app-db) nil))) diff --git a/src/re_frame/frame.cljc b/src/re_frame/frame.cljc index 2af801ba7..a27671201 100644 --- a/src/re_frame/frame.cljc +++ b/src/re_frame/frame.cljc @@ -47,7 +47,7 @@ [this id interceptors handler])) ;; connect all the pieces of state ---- -(defrecord Frame [registry event-queue app-db subscriptions-cache] +(defrecord Frame [registry event-queue app-db subs-cache] IFrame ;; dispatch ---- (dispatch [this event-v] @@ -67,7 +67,7 @@ (clear-sub [this query-id] (reg/clear-handlers registry subs/kind query-id)) (clear-subscriptions-cache [this] - (subs/clear-subscription-cache!)) + (subs/clear-subscription-cache! subs-cache)) ;; fx ---- (reg-fx [this fx-id handler-fn] diff --git a/src/re_frame/subs.cljc b/src/re_frame/subs.cljc index c226df965..6a612e380 100644 --- a/src/re_frame/subs.cljc +++ b/src/re_frame/subs.cljc @@ -15,7 +15,53 @@ ;; De-duplicate subscriptions. If two or more equal subscriptions ;; are concurrently active, we want only one handler running. ;; Two subscriptions are "equal" if their query vectors test "=". -(def query->reaction (atom {})) + +(defprotocol ICache + ;; Using -prefixed methods here because for some reason when removing the dash I get + ;; + ;; java.lang.ClassFormatError: Duplicate method name&signature in class file re_frame/subs/SubscriptionCache + ;; + ;; as far as I understand that would happen when you try to implement two identically + ;; named functions in one defrecord call but I don't see how I'm doing that here + (-clear [this]) + (-cache-and-return [this query-v dyn-v r]) + (-cache-lookup + [this query-v] + [this query-v dyn-v])) + +(defrecord SubscriptionCache [state] + #?(:cljs IDeref :clj clojure.lang.IDeref) + #?(:cljs (-deref [this] (-> this :state deref)) + :clj (deref [this] (-> this :state deref))) + ICache + (-clear [this] + (doseq [[k rxn] @state] + (dispose! rxn)) + (if (not-empty @state) + (console :warn "Subscription cache should be empty after clearing it."))) + (-cache-and-return [this query-v dyn-v r] + (let [cache-key [query-v dyn-v]] + ;; when this reaction is no longer being used, remove it from the cache + (add-on-dispose! r #(do (swap! state dissoc cache-key) + (trace/with-trace {:operation (first-in-vector query-v) + :op-type :sub/dispose + :tags {:query-v query-v + :reaction (reagent-id r)}} + nil))) + ;; cache this reaction, so it can be used to deduplicate other, later "=" subscriptions + (swap! state assoc cache-key r) + (trace/merge-trace! {:tags {:reaction (reagent-id r)}}) + r)) + (-cache-lookup [this query-v] + (-cache-lookup this query-v [])) + (-cache-lookup [this query-v dyn-v] + (get @state [query-v dyn-v]))) + +(defn clear-all-handlers! + "Unregisters all existing subscription handlers and clears the subscription cache" + [{:keys [registry subs-cache]}] + (reg/clear-handlers registry kind) + (-clear subs-cache)) (defn clear-subscription-cache! "Runs on-dispose for all subscriptions we have in the subscription cache. @@ -29,50 +75,21 @@ aren't cleaned up properly. This means a subscription's on-dispose function isn't run when the components are destroyed. If a bad subscription caused your exception, then you can't fix it without reloading your browser." - [] - (doseq [[k rxn] @query->reaction] + [subs-cache] + (doseq [[k rxn] @subs-cache] (dispose! rxn)) - (if (not-empty @query->reaction) + (if (not-empty @subs-cache) (console :warn "Subscription cache should be empty after clearing it."))) -(defn clear-all-handlers! - "Unregisters all existing subscription handlers" - [registry] - (reg/clear-handlers registry kind) - (clear-subscription-cache!)) - -(defn cache-and-return - "cache the reaction r" - [query-v dynv r] - (let [cache-key [query-v dynv]] - ;; when this reaction is no longer being used, remove it from the cache - (add-on-dispose! r #(do (swap! query->reaction dissoc cache-key) - (trace/with-trace {:operation (first-in-vector query-v) - :op-type :sub/dispose - :tags {:query-v query-v - :reaction (reagent-id r)}} - nil))) - ;; cache this reaction, so it can be used to deduplicate other, later "=" subscriptions - (swap! query->reaction assoc cache-key r) - (trace/merge-trace! {:tags {:reaction (reagent-id r)}}) - r)) ;; return the actual reaction - -(defn cache-lookup - ([query-v] - (cache-lookup query-v [])) - ([query-v dyn-v] - (get @query->reaction [query-v dyn-v]))) - - ;; -- subscribe ----------------------------------------------------- (defn subscribe "Returns a Reagent/reaction which contains a computation" - ([{:keys [registry app-db]} query-v] + ([{:keys [registry app-db subs-cache]} query-v] (trace/with-trace {:operation (first-in-vector query-v) :op-type :sub/create :tags {:query-v query-v}} - (if-let [cached (cache-lookup query-v)] + (if-let [cached (-cache-lookup subs-cache query-v)] (do (trace/merge-trace! {:tags {:cached? true :reaction (reagent-id cached)}}) @@ -84,14 +101,14 @@ (if (nil? handler-fn) (do (trace/merge-trace! {:error true}) (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))))))) + (-cache-and-return subs-cache query-v [] (handler-fn app-db query-v))))))) - ([{:keys [registry app-db]} v dynv] + ([{:keys [registry app-db subs-cache]} v dynv] (trace/with-trace {:operation (first-in-vector v) :op-type :sub/create :tags {:query-v v :dyn-v dynv}} - (if-let [cached (cache-lookup v dynv)] + (if-let [cached (-cache-lookup subs-cache v dynv)] (do (trace/merge-trace! {:tags {:cached? true :reaction (reagent-id cached)}}) @@ -110,7 +127,7 @@ ;; handler-fn returns a reaction which is then wrapped in the sub reaction ;; need to double deref it to get to the actual value. ;; (console :log "Subscription created: " v dynv) - (cache-and-return v dynv (make-reaction (fn [] @@sub)))))))))) + (-cache-and-return subs-cache v dynv (make-reaction (fn [] @@sub)))))))))) ;; -- reg-sub ----------------------------------------------------------------- diff --git a/test/re-frame/restore_test.cljs b/test/re-frame/restore_test.cljs index 8b2437477..b66a097b5 100644 --- a/test/re-frame/restore_test.cljs +++ b/test/re-frame/restore_test.cljs @@ -5,7 +5,7 @@ ;; TODO: future tests in this area could check DB state and registrations are being correctly restored. -(use-fixtures :each {:before (partial subs/clear-all-handlers! (:registry core/the-frame))}) +(use-fixtures :each {:before (partial subs/clear-all-handlers! core/the-frame)}) (defn one? [x] (= 1 x)) (defn two? [x] (= 2 x)) @@ -24,51 +24,51 @@ (deftest make-restore-fn-test (testing "no existing subs, then making one subscription" (register-test-subs) - (let [original-subs @subs/query->reaction + (let [original-subs @(:subs-cache core/the-frame) restore-fn (make-restore-fn)] (is (zero? (count original-subs))) @(subscribe [:test-sub]) - (is (one? (count @subs/query->reaction))) - (is (contains? @subs/query->reaction [[:test-sub] []])) + (is (one? (count @(:subs-cache core/the-frame)))) + (is (contains? @(:subs-cache core/the-frame) [[:test-sub] []])) (restore-fn) - (is (zero? (count @subs/query->reaction)))))) + (is (zero? (count @(:subs-cache core/the-frame))))))) (deftest make-restore-fn-test2 (testing "existing subs, making more subscriptions" (register-test-subs) @(subscribe [:test-sub]) - (let [original-subs @subs/query->reaction + (let [original-subs @(:subs-cache core/the-frame) restore-fn (make-restore-fn)] (is (one? (count original-subs))) @(subscribe [:test-sub2]) - (is (contains? @subs/query->reaction [[:test-sub2] []])) - (is (two? (count @subs/query->reaction))) + (is (contains? @(:subs-cache core/the-frame) [[:test-sub2] []])) + (is (two? (count @(:subs-cache core/the-frame)))) (restore-fn) - (is (not (contains? @subs/query->reaction [[:test-sub2] []]))) - (is (one? (count @subs/query->reaction)))))) + (is (not (contains? @(:subs-cache core/the-frame) [[:test-sub2] []]))) + (is (one? (count @(:subs-cache core/the-frame))))))) (deftest make-restore-fn-test3 (testing "existing subs, making more subscriptions with different params on same subscriptions" (register-test-subs) @(subscribe [:test-sub]) - (let [original-subs @subs/query->reaction + (let [original-subs @(:subs-cache core/the-frame) restore-fn (make-restore-fn)] (is (one? (count original-subs))) @(subscribe [:test-sub :extra :params]) - (is (two? (count @subs/query->reaction))) + (is (two? (count @(:subs-cache core/the-frame)))) (restore-fn) - (is (one? (count @subs/query->reaction)))))) + (is (one? (count @(:subs-cache core/the-frame))))))) (deftest nested-restores (testing "running nested restores" (register-test-subs) (let [restore-fn-1 (make-restore-fn) _ @(subscribe [:test-sub]) - _ (is (one? (count @subs/query->reaction))) + _ (is (one? (count @(:subs-cache core/the-frame)))) restore-fn-2 (make-restore-fn)] @(subscribe [:test-sub2]) - (is (two? (count @subs/query->reaction))) + (is (two? (count @(:subs-cache core/the-frame)))) (restore-fn-2) - (is (one? (count @subs/query->reaction))) + (is (one? (count @(:subs-cache core/the-frame)))) (restore-fn-1) - (is (zero? (count @subs/query->reaction)))))) + (is (zero? (count @(:subs-cache core/the-frame))))))) \ No newline at end of file diff --git a/test/re-frame/subs_test.cljs b/test/re-frame/subs_test.cljs index 46031a263..1b675021f 100644 --- a/test/re-frame/subs_test.cljs +++ b/test/re-frame/subs_test.cljs @@ -21,7 +21,7 @@ (test/use-fixtures :each {:before (fn [] (reset! frame (re-frame/make-frame)) - (subs/clear-all-handlers! (:registry @frame)))}) + (subs/clear-all-handlers! @frame))}) ;;=====test basic subscriptions ====== From 823930a86ea0ee56440609995fd4f4eb672b8476 Mon Sep 17 00:00:00 2001 From: Martin Klepsch Date: Tue, 20 Dec 2016 17:07:11 +0800 Subject: [PATCH 33/33] allow parameteriziation of default interceptors --- src/re_frame/core.cljc | 3 ++- src/re_frame/frame.cljc | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/re_frame/core.cljc b/src/re_frame/core.cljc index 5e7386d7d..85da8a77f 100644 --- a/src/re_frame/core.cljc +++ b/src/re_frame/core.cljc @@ -47,7 +47,8 @@ {:registry registry :event-queue event-queue :app-db re-frame.db/app-db - :subs-cache subs-cache}))) + :subs-cache subs-cache + :default-interceptors [(cofx/inject-cofx registry :db) (fx/do-fx registry)]}))) (def the-frame (make-frame)) diff --git a/src/re_frame/frame.cljc b/src/re_frame/frame.cljc index a27671201..87b02cb52 100644 --- a/src/re_frame/frame.cljc +++ b/src/re_frame/frame.cljc @@ -47,7 +47,7 @@ [this id interceptors handler])) ;; connect all the pieces of state ---- -(defrecord Frame [registry event-queue app-db subs-cache] +(defrecord Frame [registry event-queue app-db subs-cache default-interceptors] IFrame ;; dispatch ---- (dispatch [this event-v] @@ -95,18 +95,18 @@ (events/register registry id - [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/db-handler->interceptor db-handler)])) + [default-interceptors interceptors (stdi/db-handler->interceptor db-handler)])) (reg-event-fx [this id fx-handler] (reg-event-fx this id nil fx-handler)) (reg-event-fx [this id interceptors fx-handler] (events/register registry id - [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/fx-handler->interceptor fx-handler)])) + [default-interceptors interceptors (stdi/fx-handler->interceptor fx-handler)])) (reg-event-ctx [this id handler] (reg-event-ctx this id nil handler)) (reg-event-ctx [this id interceptors handler] (events/register registry id - [(cofx/inject-cofx registry :db) (fx/do-fx registry) interceptors (stdi/ctx-handler->interceptor handler)]))) + [default-interceptors interceptors (stdi/ctx-handler->interceptor handler)])))