Elmish.Hooks
- Package
- purescript-elmish-hooks
- Repository
- collegevine/purescript-elmish-hooks
A React hook-like library for Elmish. Uses a continuation monad to encapsulate state or effects.
import Elmish.Hooks (useEffect, useState)
import Elmish.Hooks as Hooks
todos :: ReactElement
todos = Hooks.component Hooks.do
todos /\ setTodos <- useState []
useEffect do
todos <- API.fetchTodos
liftEffect $ setTodos todos
Hooks.pure $ H.fragment $ todoView <$> todos
Re-exports from Elmish.Hooks.Type
#mkHook Source
mkHook :: forall msg state t a. ComponentName -> ((a -> ReactElement) -> ComponentDef msg state) -> Hook' t a
Given a ComponentName
and a function to create a ComponentDef
(from a
render function a -> ReactElement
), mkHook
creates a Hook a
. When
creating a hook with mkHook
, you’ll need to create a HookType
by
foreign import
ing it.
As an example of how to use mkHook
, useEffect
uses it like so:
foreign import data UseEffect :: Type -> HookType
useEffect :: Aff Unit -> Hook (UseEffect Unit) Unit
useEffect init =
mkHook (ComponentName "UseEffect") \render ->
{ init: forkVoid init
, update: \_ msg -> absurd msg
, view: \_ _ -> render unit
}
#component Source
component :: forall t. Hook' t ReactElement -> ReactElement
Unwraps a Hook ReactElement
, which is usually created by using one or
more hooks and then using pure
to encapsulate a ReactElement
. E.g.:
view :: ReactElement
view = Hooks.component Hooks.do
name /\ setName <- useState ""
Hooks.pure $ H.input_ "" { value: name, onChange: setName <?| eventTargetValue }
#bind Source
bind :: forall ta tb tr a b. ComposedHookTypes ta tb tr => Hook' ta a -> (a -> Hook' tb b) -> Hook' tr b
#type (<>) Source
Operator alias for Elmish.Hooks.Type.AppendHookType (right-associative / precedence 6)
Re-exports from Elmish.Hooks.UseEffect
#useEffect' Source
useEffect' :: forall @a. Eq a => a -> (a -> Aff Unit) -> Hook (UseEffect a) Unit
This is like useEffect
, but allows passing a value which, when it
changes, will trigger the effect to run again. E.g.:
view :: ReactElement
view = Hooks.component Hooks.do
count /\ setCount <- useState 0
useEffect' count \c -> liftEffect $
HTMLDocument.setTitle ("You clicked " <> show c <> " times") =<< document =<< window
Hooks.pure H.button_ "" { onClick: setCount $ count + 1 } "Click me"
#useEffect Source
useEffect :: Aff Unit -> Hook (UseEffect Unit) Unit
The useEffect
hook takes an effect (Aff
) to run and runs it in the
init
of the resulting component. E.g.:
todos :: ReactElement
todos = Hooks.component Hooks.do
todos /\ setTodos <- useState []
useEffect do
todos <- API.fetchTodos
liftEffect $ setTodos todos
Hooks.pure $ H.fragment $ todoView <$> todos
Re-exports from Elmish.Hooks.UseRef
#useRef Source
useRef :: forall @el. Hook (UseRef el) ((Maybe el) /\ (Ref el))
The useRef
hook returns a Hook
encapsulating an element paired with a
setter for that element. This setter can be passed to a ref
prop to get a
reference to an element.
view :: ReactElement
view = Hooks.component Hooks.do
inputEl /\ inputRef <- useRef
let onButtonClick = traverse_ (focus <<< HTMLInputElement.toHTMLElement) inputEl
Hooks.pure $
H.fragment
[ H.input_ "form-control" { ref: inputRef, defaultValue: "" }
, H.button_ "btn btn-primary" { onClick: onButtonClick } "Focus the input"
]
Re-exports from Elmish.Hooks.UseState
#useState Source
useState :: forall @state. state -> Hook (UseState state) (state /\ (Dispatch state))
The useState
hook takes an initial state and returns a Hook
encapsulating the current state and a setState
function. E.g.:
view :: ReactElement
view = Hooks.component Hooks.do
visible /\ setVisible <- useState false
Hooks.pure $
H.fragment
[ H.button_ "" { onClick: setVisible <| not visible } "Toggle visibility"
, if visible
then H.div "" "Content"
else H.empty
]
Re-exports from Elmish.Hooks.UseSubscription
#UseSubscription Source
data UseSubscription :: Type -> HookType
data UseSubscription t0
#useSubscription Source
useSubscription :: forall a. Subscription Aff a -> (a -> Aff Unit) -> Hook (UseSubscription a) Unit
Subscribes to the given subscription and calls the provided callback every time the subscription yields a value.
listenToNetwork :: Subscription Aff NetworkSignal
listenToNetwork = ...
view :: ReactElement
view = Hooks.component Hooks.do
lastSignal /\ setLastSignal <- Hooks.useState Nothing
useSubscription listenToNetwork \signal -> setLastSignal (Just signal)
Hooks.pure $
case lastSignal of
Nothing -> H.div "bg-secondary" "Waiting for signal..."
Just signal -> H.div "bg-success" $ "Received signal: " <> show signal