Getting started
Your first Component
The core type of miso is Component. To define one, use the component smart constructor. Below is a simple counter.
module Main where
import Miso
import Miso.Lens
import qualified Miso.Html.Element as H
import qualified Miso.Html.Event as HE
import qualified Miso.Html.Property as HP
-- The four Component type parameters:
-- context - the type of the global context
-- props - the props inherited from the parent
-- Int - the type of the Component model
-- Action - the action that updates the model
counter
:: Component context props Int Action
counter = component m u v
where
-- | Initial model value
m :: Int
m = 0
u :: Action
-> Effect context props Int Action
u = \case
Add -> this += 1
Subtract -> this -= 1
v :: Int
-> View context props Int Action
v x = vfrag
[ H.button_
[ HE.onClick Add, HP.id_ "add" ]
[ "+" ]
, text (ms x)
, H.button_
[ HE.onClick Subtract, HP.id_ "subtract" ]
[ "-" ]
]
main :: IO ()
main = startApp defaultEvents counter
data Action
= Add
| Subtract
deriving (Eq, Show)data CounterAction = Add | Subtract
deriving (Show, Eq)
counter
:: Component ctx () Int CounterAction
counter = component m u v
where
m = 0
u = \case
Add -> this += 1
Subtract -> this -= 1
v n =
H.div_ [ HP.class_ "row" ]
[ H.button_ [ HE.onClick Subtract ] [ "−" ]
, H.strong_ [] [ text (ms n) ]
, H.button_ [ HE.onClick Add ] [ "+" ]
]Four type parameters follow every Component: the global context (shared by the whole tree), the props passed by the parent, the component's own model and the action type its update consumes. A top-level application fixes context and props to (); the App synonym spells that out:
type App model action
= Component () () model action
startApp
:: Eq model
=> Events
-> App model action
-> IO ()Running it
We recommend startApp as the starting point — it sets up event listeners, performs the initial draw and assumes <body> is empty. The miso function (and prerender) assume <body> has already been populated by the result of view: instead of drawing, miso hydrates. If the structures do not match it falls back to drawing from scratch.
main :: IO ()
main = miso defaultEvents $ \uri -> counter
-- hydrate a prerendered pageDoing something on mount
It is possible to execute an initial action when a Component is first mounted with the mount hook (and, similarly, unmount):
data Action = Init | Add | Subtract
main :: IO ()
main = startApp defaultEvents
counter { mount = Just Init }
update
:: Action
-> Effect context props Int Action
update = \case
Init -> io_ (consoleLog "hello world!")
...