miso

Thinking in miso

Thinking in miso

miso can change how you think about the designs you look at and the apps you build. When you build a UI with miso you will first describe its state as data, then write a pure function from that state to the screen, and finally name the events that move the state forward. This guide walks through that process by building a small bookmarks manager.

Start with the mockup

Imagine we already have a JSON endpoint and a mockup from a designer. Here it is — except this "mockup" is already the finished application, running (the endpoint is mocked with a local list):

Loading bookmarks…
The mockup, live. Search, filter by tag, click a row for the detail pane — everything this guide builds, in ~60 lines.

and some data:

[ { "id": 1, "title": "miso on GitHub",  "url": "https://github.com/dmjio/miso", "tags": ["haskell"] }
, { "id": 2, "title": "Lynx docs",       "url": "https://lynxjs.org",             "tags": ["mobile"]  }
, { "id": 3, "title": "Elm architecture", "url": "https://guide.elm-lang.org",    "tags": ["haskell"] }
]

The four steps

  1. Design the model — write down the minimal state the UI needs, and nothing that can be computed from it.
  2. Break the UI into views and components — decide what is a plain view function and what deserves its own Component, and where each piece of state lives.
  3. Name the actions and write update — describe how the model evolves and keep IO at the edges.
  4. Connect the pieces — props down, mail up, context around; then prerender, route and ship.

The mindset in three sentences

  • State is data. Your whole UI at any instant is a plain Haskell value with an Eq instance.
  • The view is a function. view :: context -> props -> model -> View — no hidden state, no mutation, nothing to keep in sync.
  • Change is a fold. Every event is an action; update folds it into the model and schedules any IO. Results come back as more actions.

If you have written Elm, this will feel like home. If you come from React, notice that there are no hooks to order, no dependency arrays and no stale closures — the model is the only state and it is always current.