cursery.nixDocs

<web/io>

Effects, and ways to combine them. An effect describes work for the app to do. Return one from an event handler, or from update in place of a state, to run it.

Exports
let
  io = import <web/io>;
in
html.button { on.click = event: io.dispatch "increment" null; } "+"

Running effects#

Each effect has an output, which the next step in a chain receives. Chains run synchronously, rendering as they go, until an io.call effect returns a promise. Then the rest of the chain waits for it, and is dropped if the app unmounts first.

A failure skips ahead to the nearest io.catch. Failures nothing catches are logged with console.error. Values passed between steps are deeply evaluated, so a thunk that throws fails at the step that made it, not wherever it's read later.

io.dispatch#

Signature
io.dispatch type payload

Sends an action to update, which gets { type; payload; }. type is a string. Pass null for no payload. The app renders the new state, and the output is that state.

If update returns an effect instead, that runs in the dispatch's place, leaving the state as it is. The output is the effect's output.

io.call#

Signature
io.call name input

Calls the effect name the host passed to mount, with input converted to JavaScript. The output is what it returned, or what its promise resolved to. To define effects, see Host IO.

Inputs and outputs must be JSON-compatible. undefined outputs null. Errors, rejections, and missing effects fail the call, naming the effect.

io.pipe#

Signature
io.pipe value [ function ... ]

Threads value through each function in turn. When one returns an effect, the next gets its output once it runs:

Pipes
io.pipe null [
  (_: io.call "load" "count")
  (count: io.dispatch "loaded" count)
]

Returns an effect if any function returned one, or else the last function's value. io.catch handler is a step too: it handles failures of every step before it, and steps after it get its result.

io.map#

Signature
io.map function effect

Runs effect, then calls function with its output. If that returns an effect, it runs next, and its output is the chain's. Otherwise the value is.

Maps
io.map (count: io.dispatch "loaded" count) (io.call "load" "count")

io.catch#

Signature
io.catch handler effect

Runs effect. If it fails, calls handler with { message; }, and carries on from what it returns: a value, or an effect to run. Successes pass through untouched.

Catching
io.catch (error: io.dispatch "failed" error.message) (io.call "save" state)

io.all#

Signature
io.all [ effect ... ]

Runs effects in order, each after the last finishes. The output is a list of their outputs. It stops at the first failure. Values that aren't effects are outputs already.

Several effects
html.form {
  on.submit = event: io.all [ event.preventDefault (io.dispatch "save" null) ];
}

Event effects#

Snapshots of DOM events carry event.preventDefault, an effect that calls preventDefault() on the event. It fails once the event finishes dispatching, so run it before any effect that waits on a promise. See <web/dom>.