<commit_before>Maybe 20% of the time, event handlers need to cause side effects.

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 testing and event replays.

## Where Effects Come From

When an event handler is registered via `reg-event-fx`, it must return effects. Like this:
```clj
(reg-event-fx              ;; -fx registration, not -db registration
  :my-event
  (fn [cofx [_ a]]        ;; 1st argument is coeffects, instead of db
    {:db       (assoc (:db cofx) :flag  a)
     :dispatch [:do-something-else 3]}))   ;; return effects
```

`-fx` handlers return a description of the side-effects required, and that description is a map.

## The Effects Map

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 type of value depends on the specific side-effect.

Here's the two instructions from the example above:
```clj
{: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.

And the `:dispatch` key instructs that an event should be
dispatched. The value is the vector to dispatch.

There are many other possible
effects, like for example `:dispatch-later`, `dispatch-n`, `:set-local-store`, etc.

And so on. And so on. Which brings us to a problem.

## Infinite Effects

Although re-frame supplies a number of built-in effect handlers, the set of
possible effects is open ended.

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`. Or save cookies.

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
your own side effects.

## Extensible Side Effects

re-frame provides a function `reg-fx` through which you can register
your own `Effect Handlers`. Use it like this:
```clj
(reg-fx         ;; <-- registration function
   :butterfly   ;;  <1>
   (fn [value]  ;;  <2>
      ...
      ))
```

__<1>__  the key for the effect.  When later an effects map contains
the key `:butterfly`, the function we are registering will be used to action it.

__<2>__  the function which actions the side effect. Later, it will be called
with one argument - the value in the effects map, for this key.

So, if an event handler returned these two effects:
```clj
{:dispatch   [:save-maiden 42]
 :butterfly  "Flapping"}         ;; butterfly effect, but no chaos !!
```

Then the function we registered for `:butterfly` would be called to handle<commit_msg>Update Effects.md<commit_after>Maybe 20% of the time, event handlers need to cause side effects.

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 testing and event replays.

## Where Effects Come From

When an event handler is registered via `reg-event-fx`, it must return effects. Like this:
```clj
(reg-event-fx              ;; -fx registration, not -db registration
  :my-event
  (fn [cofx [_ a]]        ;; 1st argument is coeffects, instead of db
    {:db       (assoc (:db cofx) :flag  a)
     :dispatch [:do-something-else 3]}))   ;; return effects
```

`-fx` handlers return a description of the side-effects required, and that description is a map.

## The Effects Map

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 type of value depends on the specific side-effect.

Here's the two instructions from the example above:
```clj
{: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.

And the `:dispatch` key instructs that an event should be
dispatched. The value is the vector to dispatch.

There are many other possible
effects, like for example `:dispatch-later`, `dispatch-n`, `:set-local-store`, etc.

And so on. And so on. Which brings us to a problem.

## Infinite Effects

Although re-frame supplies a number of built-in effect handlers, the set of
possible effects is open ended.

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`. Or save cookies.

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
your own side effects.

## Extensible Side Effects

re-frame provides a function `reg-fx` through which you can register
your own `Effect Handlers`. Use it like this:
```clj
(reg-fx         ;; <-- registration function
   :butterfly   ;;  <1> event key
   (fn [value]  ;;  <2> effect handler
      ...
      ))
```

__<1>__  __Event Key__  Later, when an effects map contains
the key `:butterfly`, the function we are registering will be used to action it.

__<2>__  __Effect handler__ The function which actions the side effect. Later, it will be called
with one argument - the value in the effects map, for this key.

So, if an event handler returned these two effects:
```clj
{:dispatch   [:save-maiden 42]
 :butterfly  "Flapping"}         ;; butterfly effect, but no chaos !!
```

Then the function we registered for `:butterfly` would be called to handle
{'fraction_non_alphanumeric': 0.08045977011494253, 'fraction_numerical': 0.003774232286841654, 'mean_word_length': 3.508894044856922, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5474069', 'n_tokens_mistral': 1704, 'n_tokens_neox': 1606, 'n_words': 859}