Module

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

#Hook Source

type Hook :: (HookType' -> HookType') -> Type -> Typetype Hook (t :: HookType) a = Hook' (t Pure) a

A Convenient wrapper which applies Pure to the given hook type.

#pure Source

pure :: forall a. a -> Hook' Pure a

#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 importing 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
    }

#discard Source

discard :: forall ta tb tr a b. Discard a => ComposedHookTypes ta tb tr => Hook' ta a -> (a -> Hook' tb b) -> Hook' tr b

#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

#(==>) Source

Operator alias for Elmish.Hooks.Type.withHook (left-associative / precedence 1)

#(=/>) Source

Operator alias for Elmish.Hooks.Type.withHookCurried (left-associative / precedence 1)

#type (<>) Source

Operator alias for Elmish.Hooks.Type.AppendHookType (right-associative / precedence 6)

Re-exports from Elmish.Hooks.UseEffect

#UseEffect Source

data UseEffect :: Type -> HookTypedata UseEffect t0

#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

type UseRef :: Type -> HookType' -> HookType'type UseRef el = UseState (Maybe el)

#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

data UseState :: Type -> HookTypedata UseState t0

#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
    ]