Skip to content

Commit

Permalink
[docs] polish
Browse files Browse the repository at this point in the history
  • Loading branch information
kimo-k committed Nov 23, 2023
1 parent 36b832e commit 3600560
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
7 changes: 4 additions & 3 deletions docs/FAQs/UseASubscriptionInAnEventHandler.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ But this comes with a caveat: **the only safe place to call `subscribe` is withi
Inner functions, such as DOM event handlers, don't count. Consider this component:

```clj
[:button {:on-click #(subscribe [:some (gensym)])}]
(defn my-btn []
[:button {:on-click #(subscribe [:some (gensym)])}])
```

Our `:on-click` function isn't actually called here. Instead, we've given the function to the browser, expecting it to get called later. The problem is, reagent and re-frame have no way to safely manage your subscription at that time. The result is a memory leak. If the browser calls your `:on-click` a thousand times, re-frame will "create" a thousand unique subscriptions, and there's no code in place to "dispose" them later.
Our `:on-click` function isn't actually called when the component renders. Instead, we've given the function to the browser, expecting it to get called later. The problem is, reagent and re-frame have no way to safely manage your subscription at that time. The result is a memory leak. If the browser calls your `:on-click` a thousand times, re-frame will "create" a thousand unique subscriptions, and there's no code in place to "dispose" them later.

### Re-frame event handlers

Expand All @@ -41,7 +42,7 @@ Re-frame event handlers don't count either. Re-frame calls your event handlers w

Furthermore, this is a conceptual issue.
Your subscription handler may be pure, but `subscribe` always has a side-effect.
Calling `subscribe` inside an event handler goes against re-frame's design, which is based on handlers being pure functions.
Calling `subscribe` inside an event handler goes against re-frame's design, which is based on [handlers being pure functions](/re-frame/on-dynamics/#pure-functions).

### Incidental safety

Expand Down
41 changes: 24 additions & 17 deletions docs/Flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,6 @@ And, we use this subscription in a view:

<div id="garage-calculator"></div>


!!! Note "Our dataflow model"
Dataflow is often conceptualized as a graph.
Data flows through edges, and transforms through nodes.
Here's how our DSL articulates the traditional dataflow model:

- `flow` - a map, serving as a node specification
- `:id` - uniquely identifies a node
- `:inputs` - a set of edges from other nodes
- `reg-flow` - creates a running node from a specification

Crucially, the name `flow` isn't exactly short for "dataflow".
A `flow` is a static value, specifying one possible segment of a dataflow graph.
Dataflow is a [dynamic process](/re-frame/on-dynamics/#on-dynamics), not a value.
Both the data and the graph itself change over time.
Changing the graph is a matter of [registering and clearing](#redefining-and-undefining) flows.

## How does it work?

`event handlers` yield `effects`. Typically, they yield a `:db` effect, causing a new value of `app-db`.
Expand Down Expand Up @@ -300,6 +283,30 @@ When either input changes value, our flow calls the `:output` function to recalc
As before, once `:output` runs, the resulting value is stored at `:path`.
So, the new value of `app-db` will contain a number at the path `[:ratios :main-rooms]`

Under the hood, flows relate to each other in a depedency graph.
An input like `(rf/flow<- ::kitchen-area)` creates a dependency.
That means re-frame will always run `::kitchen-area` first,
ensuring its output value is current before your `:main-room-ratio` flow can use it.

!!! Note "Our dataflow model"
Dataflow is often conceptualized as a graph.
Data flows through edges, and transforms through nodes.
Here's how our DSL articulates the traditional dataflow model:

- `flow` - a map, serving as a node specification
- `:id` - uniquely identifies a node
- `:inputs` - a set of edges from other nodes
- `flow<-` - declares another node id as an input dependency
- `reg-flow` - creates a running node from a specification

Crucially, the name `flow` isn't exactly short for "dataflow".
A `flow` is a static value, specifying one possible segment of a dataflow graph.
Dataflow is a [dynamic process](/re-frame/on-dynamics/#on-dynamics), not a value.
Both the data and the graph itself can change over time.

- Changing the data means running the flows which are currently registered.
- Changing the graph is a matter of [registering and clearing](#redefining-and-undefining) flows.

## Subscribing to flows

In our examples so far, we've used a regular subscription, getting our flow's output path.
Expand Down

0 comments on commit 3600560

Please sign in to comment.