Skip to content

Commit 1d81f23

Browse files
committed
Explain why event-fx handlers can't return cofx maps
1 parent 81e8f30 commit 1d81f23

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

docs/FAQs/use-cofx-as-fx.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!-- leave this H1 here. It stops mkdocs putting in a Title at the top.
2+
It needs to be at the top of the file otherwise it breaks the
3+
table of contents on the right hand side. -->
4+
#
5+
6+
## Question
7+
8+
With `reg-event-fx`, why can't my handler function just update the first argument (i.e. the `cofx` map) and pass it on?
9+
10+
When I try, I get a warning, such as: `no handler registered for effect: :event. Ignoring.`
11+
12+
## Answer
13+
14+
Effects simply aren't coeffects.
15+
16+
To fix this warning, just declare a new map of effects. For instance:
17+
18+
```clj
19+
(reg-event-fx ::cow-clicked
20+
(fn [{:keys [db] :as cofx} _]
21+
{:db (update db :clicks inc)}))
22+
```
23+
24+
## Context
25+
26+
This seems like it would work, if you're used to using `reg-event-db` this way.
27+
Such a `db` handler behaves like a reducing function:
28+
29+
```clj
30+
(reg-event-db ::cow-clicked-db
31+
(fn [db _] (update db :clicks inc)))
32+
```
33+
34+
Doing a similar thing to a coeffect map causes the warning, however, not to mention possible unintended effects:
35+
36+
```clj
37+
(reg-event-fx ::cow-clicked-bad
38+
(fn [cofx _] (update-in cofx [:db :clicks] inc)))
39+
```
40+
41+
With `reg-event-fx`, you receive a map of coeffect values, and you're expected to return a map of effect values.
42+
It's a coincidence that `:db` identifies both an effect *and* a coeffect.
43+
But re-frame adds other coeffects, such as `:event`, which it does *not* consider effects.
44+
45+
So your handler ends up doing `(update-in {:db {:clicks 0} :event [::cow-clicked-bad] :your-other-coeffect 25} ...)`.
46+
47+
There's probably no effect handler for `:event`. Hence the warning.
48+
Coeffects which you declare, such as `your-other-coeffect`, may cause the same problem.
49+
50+
You might have a coeffect, similar to `:db`, which shares its name with an effect. But that's a deliberate design decision, not a default.

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ nav:
8484
- "Why is my input field laggy?": FAQs/laggy-input.md
8585
- "How long after I do a dispatch does the event get handled?": FAQs/When-Does-Dispatch-Happen.md
8686
- "How can I use a subscription in an Event Handler": FAQs/UseASubscriptionInAnEventHandler.md
87+
- "Why can't I turn a `cofx` map into an `fx` map?": FAQs/use-cofx-as-fx.md
8788
- "How do I use logging method X": FAQs/Logging.md
8889
- "Dispatched Events Are Null": FAQs/Null-Dispatched-Events.md
8990
- "Why do we need to clear the subscription cache when reloading with Figwheel?": FAQs/Why-Clear-Sub-Cache.md

src/re_frame/fx.cljc

+7-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@
5656
(doseq [[effect-key effect-value] effects-without-db]
5757
(if-let [effect-fn (get-handler kind effect-key false)]
5858
(effect-fn effect-value)
59-
(console :warn "re-frame: no handler registered for effect:" effect-key ". Ignoring."))))))))
59+
(console :warn
60+
"re-frame: no handler registered for effect:"
61+
effect-key
62+
". Ignoring."
63+
(when (= :event effect-key)
64+
(str "You may be trying to return a coeffect map from an event-fx handler. "
65+
"See https://day8.github.io/re-frame/use-cofx-as-fx/"))))))))))
6066

6167
;; -- Builtin Effect Handlers ------------------------------------------------
6268

0 commit comments

Comments
 (0)