-
Notifications
You must be signed in to change notification settings - Fork 0
/
Mount.purs
64 lines (50 loc) · 1.91 KB
/
Mount.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
module Chameleon.Impl.ReactBasic.Mount where
import Prelude
import Effect (Effect)
import React.Basic.DOM.Client as ReactBasicDOM
import React.Basic.Hooks (useEffectAlways, (/\))
import React.Basic.Hooks as React
import Chameleon.Impl.ReactBasic.Html (ReactHtml, defaultConfig, runReactHtml)
import Web.DOM as DOM
--------------------------------------------------------------------------------
-- Types
--------------------------------------------------------------------------------
type UI html msg sta =
{ view :: sta -> html msg
, update :: msg -> sta -> sta
, init :: sta
}
--------------------------------------------------------------------------------
-- React Component
--------------------------------------------------------------------------------
uiToReactComponent
:: forall msg sta
. { onStateChange :: sta -> Effect Unit }
-> UI ReactHtml msg sta
-> React.Component {} -- {setState :: sta -> Effect Unit}
uiToReactComponent { onStateChange } ui = do
React.component "Root" \_props -> React.do
state /\ setState <- React.useState $ ui.init
useEffectAlways do
onStateChange state
pure $ pure unit
let
handler :: msg -> Effect Unit
handler msg = do
setState $ ui.update msg
pure
$ runReactHtml { handler } defaultConfig
$ ui.view state
--------------------------------------------------------------------------------
-- Mounting
--------------------------------------------------------------------------------
mountAtId :: String -> React.Component {} -> Effect Unit
mountAtId id comp = do
rootElem <- elemById id
app <- comp
reactRoot <- ReactBasicDOM.createRoot rootElem
ReactBasicDOM.renderRoot reactRoot (app {})
--------------------------------------------------------------------------------
-- FFI
--------------------------------------------------------------------------------
foreign import elemById :: String -> Effect DOM.Element