Skip to content

Instantly share code, notes, and snippets.

@pete-murphy
Created May 15, 2024 20:56
Show Gist options
  • Save pete-murphy/4b2ba784bb40c01711c97525015c1b66 to your computer and use it in GitHub Desktop.
Save pete-murphy/4b2ba784bb40c01711c97525015c1b66 to your computer and use it in GitHub Desktop.
module Main where
import Prelude
import Data.Maybe (Maybe(..))
import Data.Map as Map
import Data.Traversable as Traversable
import Effect (Effect)
import Effect.Exception as Exception
import Effect.Unsafe as Effect.Unsafe
import React.Basic.DOM as DOM
import React.Basic.DOM.Client as Client
import React.Basic.DOM.Events as DOM.Events
import React.Basic.Events as Events
import React.Basic.Hooks (Component, (/\))
import React.Basic.Hooks as Hooks
import React.Basic.StrictMode as StrictMode
import Unsafe.Coerce as Unsafe.Coerce
import Web.DOM.NonElementParentNode as NonElementParentNode
import Web.HTML as HTML
import Web.HTML.HTMLDocument as HTMLDocument
import Web.HTML.Window as Window
import Web.HTML.HTMLInputElement as HTMLInputElement
mkApp :: Component Unit
mkApp = do
Hooks.component "App" \_ -> Hooks.do
ref <- Hooks.useRef (Map.empty)
submittedForm /\ setSubmittedForm <- Hooks.useState' Nothing
let
input props =
DOM.label
{ style: DOM.css { display: "grid", gap: "0.5rem" }
, children:
[ DOM.text (props.label)
, DOM.input
{ ref: Unsafe.Coerce.unsafeCoerce \element -> Effect.Unsafe.unsafePerformEffect do
map <- Hooks.readRef ref
Hooks.writeRef ref (Map.insert props.name element map)
, name: props.name
, style: DOM.css { padding: "0.5rem", fontSize: "1rem" }
}
]
}
pure
( DOM.div_
[ DOM.form
{ onSubmit: Events.handler DOM.Events.preventDefault \_ -> do
values <- Hooks.readRef ref
>>= Traversable.traverse (HTMLInputElement.fromNode >>> Traversable.traverse HTMLInputElement.value)
<#> Map.catMaybes
<#> Map.toUnfoldable
setSubmittedForm (Just values)
, style: DOM.css { display: "grid", gap: "1rem", maxWidth: "60ch" }
, children:
[ input { name: "firstName", label: "First name" }
, input { name: "lastName", label: "Last name" }
, input { name: "address1", label: "Address 1" }
, input { name: "address2", label: "Address 2" }
, DOM.button_ [ DOM.text "Submit" ]
]
}
, DOM.hr {}
, case submittedForm of
Just form -> DOM.div_
[ DOM.text "Form submitted"
, DOM.ul_
( form <#> \(key /\ value) ->
DOM.li_ [ DOM.text key <> DOM.text ": " <> DOM.text value ]
)
]
Nothing -> DOM.div_
[ DOM.text "Form not submitted"
]
]
)
main :: Effect Unit
main = do
maybeRoot <- HTML.window
>>= Window.document
>>= HTMLDocument.toNonElementParentNode
>>> NonElementParentNode.getElementById "root"
case maybeRoot of
Nothing -> Exception.throw "Root element not found."
Just root -> do
app <- mkApp
reactRoot <- Client.createRoot root
Client.renderRoot reactRoot (StrictMode.strictMode (app unit))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment