This commit is contained in:
Mike Thompson 2016-12-07 09:57:20 +11:00
parent 7a39b7a660
commit 80363519e8
4 changed files with 75 additions and 35 deletions

View File

@ -28,7 +28,7 @@ Perhaps:
`reactive programming`, `functional programming` and `immutable data` going to
**completely change everything**? And, if so, what would that look like in a language
that embraces those paradigms?
3. You're taking a [Functional Design and Programming course at San Diego State University](http://www.eli.sdsu.edu/courses/fall15/cs696/index.html)
3. You're taking a [Functional Design and Programming course](http://www.eli.sdsu.edu/courses/fall15/cs696/index.html) at San Diego State University
and you have a re-frame/reagent assignment due. You've left the reading a bit late, right? I remember those days.
4. re-frame is impressively buzzword compliant: it has reactivity,
unidirectional data flow, pristinely pure functions,
@ -88,7 +88,7 @@ Computationally, each iteration of the loop involves a
six domino cascade.
One domino triggers the next, which triggers the next, et cetera, until we are
back at the beginning of the loop, whereupoon the dominoes all spring to attention
back at the beginning of the loop, whereupon the dominoes all spring to attention
again, ready for the next iteration of the same cascade.
Here are the six dominoes ...
@ -118,12 +118,12 @@ change, but sometimes the outside world must also be effected
### 3rd Domino - Effect Handling
The descriptions of `effects` are realised (actioned). This is where the mutation happens.
The descriptions of `effects` are realised (actioned). This is where mutations happens.
Now, to a functional programmer, `effects` are scary in a
[xenomorph kind of way](https://www.google.com.au/search?q=xenomorph).
Nothing messes with functional purity
quite like the need for side effects. But, on the other hand, `effects` are equally
quite like the need for side effects. On the other hand, `effects` are
marvelous because they move the app forward. Without them, an app stays stuck in one state forever,
never achieving anything.
@ -140,7 +140,7 @@ would an in-memory, central database for the app (more 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 for it
### 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)`
@ -209,7 +209,7 @@ The loop itself is very mechanical in operation.
So, there's a regularity, simplicity and
certainty to how a re-frame app goes about its business,
which leads, in turn, to an ease in reasoning and debugging. This is
key to why re-frame is so pleasing to work with - it is just so
key to why re-frame is pleasing to work with - it is just so
straightforward.
## Managing mutation
@ -218,7 +218,7 @@ The two sub-cascades 1-2-3 and 4-5-6 have a similar structure.
In each, it is the second to last domino which
computes "descriptions" of mutations required, and it is
the last domino which does the dirty work and realises these descriptions.
the last domino which does the dirty work and realises these descriptions.
In both cases, you don't need to worry yourself about this dirty work. re-frame looks
after those dominoes.
@ -255,12 +255,12 @@ it has 2 elements: `[:delete-item 2486]`. The first element,
### Code For Domino 2
The `event handler`, `h`, associated with
`:delete-item` is called to compute the `effect` of this event.
`:delete-item`, is called to compute the `effect` of this event.
This handler function, `h`, must take two arguments: the state-of-the-world
and the event, and it must return an effects map. Without going into any
explanations at this early point, here's a sketch of what a handler
might look like:
This handler function, `h`, takes two arguments: a `coeffects` map
which holds the current state of the world (including app state),
and the `event`. It must return a map of `effects` - a description
of how the world should change. Here's a sketch (we are at 30,000 feet):
```clj
(defn h
[{:keys [db]} event] ;; args: db from coeffect, event
@ -268,11 +268,18 @@ might look like:
{:db (dissoc-in db [:items item-id])})) ;; effect is change db
```
There are mechanisms in re-frame (beyond us here) whereby you can place
all necessary aspects of the world into that first `coeffects` argument, on a
per event-kind basis (different events need to know different things
in order to get their job done). The current application state, `db`,
is one aspect of the world which is invariably needed.
On program startup, `h` would have been
associated with `:delete-item` `events` like this:
```clj
(re-frame.core/reg-event-fx :delete-item h)
```
Which says "when you see a `:delete-item` event, use `h` to handle it".
### Code For Domino 3
@ -280,13 +287,13 @@ An `effect handler` (function) actions the `effects` returned by `h`:
```clj
{:db (dissoc-in db [:items item-id])}
```
So that's a map. The keys identify the required kind of `effect`, and the values
supply further details.
So that's a map. The keys identify the required kinds of `effect`, and the values
supply further details. This map only has one key, so there's only one effect.
A key of `:db` means to update the app state, with the new computed value.
A key of `:db` means to update the app state with the key's value.
This update of "app state" is a mutative step, facilitated by re-frame
when it sees a `:db` effect.
which has a built in effects handler for the `:db` effect.
Why the name `:db`? re-frame sees "app state" as something of an in-memory
database.
@ -311,6 +318,7 @@ On program startup, such a query-fn must be associated with an id,
```clj
(re-frame.core/reg-sub :query-items query-fn)
```
Which says "when you see a query (subscribe) for `:query-items`, use `query-fn` to handle it".
### Code For Domino 5
@ -329,8 +337,7 @@ for the deleted item, obviously, but otherwise the same DOM as last time).
```
Notice how `items` is "sourced" from "app state" via `subscribe`. It is called with a query id
to identify what data it needs - in Domino 4 we associated the query id `:query-items` with
the function for that computation).
to identify what data it needs.
### Code For Domino 6
@ -471,13 +478,13 @@ represent a point in the possible design space, with pros and cons.
And, yes, re-frame is fast, straight out of the box. And, yes, it has
a good testing story (unit and behavioural). And, yes, it works in with figwheel to create
a delightful hot-loading development story. And, yes, it has
a powerful hot-loading development story. And, yes, it has
fun specialist tooling, and a community,
and useful 3rd party libraries.
## Where Do I Go Next?
We haven't looked at much code yet, but **at this point you
**At this point you
already know 50% of re-frame.** There's detail to fill in, for sure,
but the core concepts, and even basic coding techniques, are now known to you.

View File

@ -1,6 +1,16 @@
## Initial Code Walk-through
At this point in your reading, 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)
In this tutorial, **we'll look at re-frame code**.
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
## Table Of Contents
### Table Of Contents
- [Initial Code Walk-through](#initial-code-walk-through)
- [What Code?](#what-code)
@ -23,14 +33,6 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Initial Code Walk-through
At this point in your reading, 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)
In this tutorial, **we'll look at re-frame code**. Finally.
## What Code?
This repo contains an example application called ["simple"](https://github.com/Day8/re-frame/tree/develop/examples/simple),
@ -43,15 +45,25 @@ enough to start coding by yourself.
## What Does It Do?
This app:
- displays the current time in a nice big font
- displays the current time in a nice big, colourful font
- provides a text input field into which you can type a hex colour code,
like "#CCC", for the time display
XXX screenshot
XXX How to run it
To run the code:
A. Install Java 8 (http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
B. Install leiningen (http://leiningen.org/#install)
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
The source file we'll be reviewing is:
https://github.com/Day8/re-frame/blob/master/examples/simple/src/simpleexample/core.cljs
XXX path to code
## Namespace

View File

@ -0,0 +1,21 @@
### Question
How can I detect exceptions in Event Handlers?
### Answer
A suggested solution can be found in [this issue](https://github.com/Day8/re-frame/issues/231#issuecomment-249991378).
***
Up: [FAQ Index](README.md)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<!-- DOCTOC SKIP
We put these inside a comment so that they are hidden when rendered on Github.
<!-- START doctoc -->
<!-- END doctoc -->
-->

View File

@ -3,7 +3,7 @@
## Table Of Contents
- [Frequently Asked Questions](#frequently-asked-questions)
- [Want To Add An FAQ?](#want-to-add-an-faq)
- [Want To Add An FAQ?](#want-to-add-an-faq)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -14,10 +14,10 @@
3. [Dispatched Events Are Null](Null-Dispatched-Events.md)
4. [Why implement re-frame in `.cljc` files](Why-CLJC.md)
5. [Why do we need to clear the subscription cache when reloading with Figwheel?](Why-Clear-Sub-Cache.md)
6. [How can I detect exceptions in Event Handlers?](CatchingEventExceptions.md)
### Want To Add An FAQ?
## Want To Add An FAQ?
We'd like that. Please supply a PR. Or just open an issue. Many Thanks!!