Skip to content

Instantly share code, notes, and snippets.

@mtamc
Last active May 21, 2026 20:17
Show Gist options
  • Select an option

  • Save mtamc/073a24ad1e9fc49a6bc6094a1d9dd7a0 to your computer and use it in GitHub Desktop.

Select an option

Save mtamc/073a24ad1e9fc49a6bc6094a1d9dd7a0 to your computer and use it in GitHub Desktop.
{-
Equivalent Miso pattern for the following React pattern:
```tsx
import React from 'react'
const Counter = () => {
const [counterState, setCounterState] = React.useState(0)
const onPlusClicked = () => setCounterState((prev) => prev + 1)
return (
<div>
<p>Counter: {counterState}</p>
<Plus onClick={onPlusClicked} />
</div>
)
}
const Plus = (props: { onClick: () => void }) => {
return <button onClick={props.onClick}>+</button>
}
```
This is untested pseudocode, but similar to what I've been using in a real app.
-}
counterComponent :: Component parent CounterModel CounterAction
counterComponent =
(component (CounterModel 0 0) updateCounter viewCounter)
{ mount = Just HandleMounted
, mailbox = checkMail HandleInbound (const NoOp)
}
data CounterModel = CounterModel
{ componentId :: ComponentId
, counterValue :: Int
}
data CounterAction
= HandleMounted
| HandleInbound InboundMessage
| ChangeCounterValue Int
| NoOp
data InboundMessage
= PlusClicked
-- This is pseudocode, ensure the JSON instances are correct
deriving (Generic, Miso.JSON.FromJSON, Miso.JSON.ToJSON)
updateCounter :: CounterAction -> Effect parent CounterModel CounterAction
updateCounter = \case
HandleMounted -> do
cId <- asks _componentInfoId
modify (\m -> m{componentId = cId})
HandleInbound PlusClicked ->
modify (\m -> m{counterValue = m.counterValue + 1})
ChangeCounterValue newValue ->
modify (\m -> m{counterValue = newValue})
NoOp ->
pure ()
viewCounter :: CounterModel -> View parent CounterAction
viewCounter counterModel =
H.div_
[]
[ H.p_ [] [text ("Counter: " <> ms counterModel.counterValue)]
, "plus-button" +> plusComponent (counterModel.componentId, PlusClicked)
]
----------------------------------------------------------------------------------------------------
plusComponent ::
(Miso.JSON.ToJSON message) =>
(ComponentId, message) -> Component parent () PlusAction
plusComponent onPlusClicked = component () (updatePlus onPlusClicked) viewPlus
data PlusAction = HandleSelfClicked
updatePlus ::
(Miso.JSON.ToJSON message) =>
(ComponentId, message) -> PlusAction -> Effect parent () PlusAction
updatePlus onSelfClicked HandleSelfClicked = do
Miso.io_ . uncurry Miso.mail $ onSelfClicked
viewPlus :: () -> View parent PlusAction
viewPlus () =
H.button_
[ E.onClick HandleSelfClicked
, CSS.style_ [CSS.marginLeft "10px"]
]
["+"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment