Skip to content

Commit

Permalink
Add ComponentsMultiTypeReactHooks
Browse files Browse the repository at this point in the history
  • Loading branch information
pete-murphy committed Dec 6, 2020
1 parent 1644a08 commit 756a44e
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 0 deletions.
15 changes: 15 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/bower_components/
/node_modules/
/.pulp-cache/
/output/
/generated-docs/
/.psc-package/
/.psc*
/.purs*
/.psa*
/.spago
/.cache/
/dist/
/web-dist/
/prod-dist/
/prod/
14 changes: 14 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# ComponentsMultiTypeReactHooks

Demonstrates a parent component with several children components, each with different prop types.

## Expected Behavior:

### Browser

A toggle button, a count button, and an input field are the children of the parent. The user can modify the state of any of those inputs and then click the "Check now" button. This will update the most recent observed state.

## Dependencies Used:

[react](https://www.npmjs.com/package/react)
[react-dom](https://www.npmjs.com/package/react-dom)
11 changes: 11 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/spago.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{ name = "ComponentsMultiTypeReactHooks"
, dependencies =
[ "console"
, "effect"
, "psci-support"
, "react-basic-hooks"
, "react-basic-dom"
]
, packages = ../../packages.dhall
, sources = [ "recipes/ComponentsMultiTypeReactHooks/src/**/*.purs" ]
}
136 changes: 136 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/src/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
module ComponentsMultiTypeReactHooks.Main where

import Prelude
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Tuple (fst)
import Effect (Effect)
import Effect.Exception (throw)
import React.Basic.DOM (render)
import React.Basic.DOM as R
import React.Basic.DOM.Events (targetValue)
import React.Basic.Events (EventHandler, handler, handler_)
import React.Basic.Hooks
( Component
, Hook
, UseState
, component
, useState
, useState'
, (/\)
, type (/\)
)
import React.Basic.Hooks as React
import Web.HTML (window)
import Web.HTML.HTMLDocument (body)
import Web.HTML.HTMLElement (toElement)
import Web.HTML.Window (document)

main :: Effect Unit
main = do
body <- body =<< document =<< window
case body of
Nothing -> throw "Could not find body."
Just b -> do
container <- mkContainer
render (container unit) (toElement b)

mkContainer :: Component Unit
mkContainer = do
componentA <- mkComponentA
componentB <- mkComponentB
componentC <- mkComponentC
component "Container" \_ -> React.do
observedState /\ setObservedState <-
useState' { a: Nothing, b: Nothing, c: Nothing }
enabledState <- useState false
countState <- useState 0
inputState <- useInput ""
pure
$ R.div_
[ R.div
{ className: "box"
, children:
[ R.h1_ [ R.text "Component A" ]
, componentA enabledState
]
}
, R.div
{ className: "box"
, children:
[ R.h1_ [ R.text "Component B" ]
, componentB countState
]
}
, R.div
{ className: "box"
, children:
[ R.h1_ [ R.text "Component C" ]
, componentC inputState
]
}
, R.p_
[ R.text "Last observed states:" ]
, R.ul_
[ R.li_ [ R.text ("Component A: " <> show observedState.a) ]
, R.li_ [ R.text ("Component B: " <> show observedState.b) ]
, R.li_ [ R.text ("Component C: " <> show observedState.c) ]
]
, R.button
{ onClick:
handler_ do
setObservedState
{ a: Just (fst enabledState)
, b: Just (fst countState)
, c: Just (fst inputState)
}
, children: [ R.text "Check states now" ]
}
]

type SetState state
= (state -> state) -> Effect Unit

mkComponentA :: Component (Boolean /\ SetState Boolean)
mkComponentA =
component "Component A" \(enabled /\ setEnabled) ->
pure
$ R.div_
[ R.p_ [ R.text "Toggle me!" ]
, R.button
{ onClick: handler_ (setEnabled not)
, children: [ R.text (if enabled then "On" else "Off") ]
}
]

mkComponentB :: Component (Int /\ SetState Int)
mkComponentB =
component "Component B" \(count /\ setCount) ->
pure
$ R.div_
[ R.p_
[ R.text "Current value: "
, R.strong_ [ R.text (show count) ]
]
, R.button
{ onClick: handler_ (setCount (_ + 1))
, children: [ R.text "Increment" ]
}
]

mkComponentC :: Component (String /\ EventHandler)
mkComponentC =
component "Component C" \(value /\ onChange) ->
pure
$ R.label_
[ R.p_ [ R.text "What do you have to say?" ]
, R.input { value, onChange }
]

useInput :: String -> Hook (UseState String) (String /\ EventHandler)
useInput initialValue = React.do
state /\ setState <- useState' ""
let
onChange =
handler
targetValue \t -> setState (fromMaybe "" t)
pure (state /\ onChange)
12 changes: 12 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ComponentsMultiTypeReactHooks</title>
</head>

<body>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions recipes/ComponentsMultiTypeReactHooks/web/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
require("../../../output/ComponentsMultiTypeReactHooks.Main/index.js").main();

0 comments on commit 756a44e

Please sign in to comment.