Skip to content

Hook creation and aliasing/newtyping #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 14, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ If we prefer this API over the existing react-basic API, we may eventually repla
## Example

```purs
mkCounter :: CreateComponent {}
mkCounter :: Effect (ReactComponent {})
mkCounter = do
component "Counter" \props -> React.do
counter /\ setCounter <- useState 0
Expand Down
7 changes: 4 additions & 3 deletions examples/aff/src/AffEx.purs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ module AffEx where
import Prelude
import Data.Either (either)
import Data.Maybe (Maybe(..), maybe)
import Effect (Effect)
import Effect.Aff (Aff, Milliseconds(..), delay, error, message, throwError)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (type (/\), CreateComponent, Hook, JSX, component, element, fragment, useState, (/\))
import React.Basic.Hooks (type (/\), ReactComponent, Hook, JSX, component, element, fragment, useState, (/\))
import React.Basic.Hooks as React
import React.Basic.Hooks.Aff (useAff)

mkAffEx :: CreateComponent {}
mkAffEx :: Effect (ReactComponent {})
mkAffEx = do
-- A component for fetching and rendering a Cat entity.
catDetails <- mkCatDetails
Expand Down Expand Up @@ -68,7 +69,7 @@ mkAffEx = do
-- Hooks can't be used conditionally but components can!
-- Not needing to deal with a `Maybe` key simplifies this
-- compoennt a bit.
mkCatDetails :: CreateComponent { catKey :: Key Cat }
mkCatDetails :: Effect (ReactComponent { catKey :: Key Cat })
mkCatDetails = do
component "CatDetails" \{ catKey } -> React.do
cat <- useAff catKey $ fetch catKey
Expand Down
20 changes: 10 additions & 10 deletions examples/component/src/Container.purs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
module Container where

import Prelude

import React.Basic.Hooks(CreateComponent, component, element)
import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.Hooks (ReactComponent, component, element)
import ToggleButton (mkToggleButton)

mkToggleButtonContainer :: CreateComponent {}
mkToggleButtonContainer :: Effect (ReactComponent {})
mkToggleButtonContainer = do
toggleButton <- mkToggleButton

component "Container" \_ ->
pure $ R.div
{ children:
[ element toggleButton { label: "A" }
, element toggleButton { label: "B" }
]
}
pure
$ R.div
{ children:
[ element toggleButton { label: "A" }
, element toggleButton { label: "B" }
]
}
23 changes: 11 additions & 12 deletions examples/component/src/ToggleButton.purs
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
module ToggleButton where

import Prelude

import Effect (Effect)
import Effect.Console (log)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (CreateComponent, component, useEffect, useState, (/\))
import React.Basic.Hooks (ReactComponent, component, useEffect, useState, (/\))
import React.Basic.Hooks as React

mkToggleButton :: CreateComponent { label :: String }
mkToggleButton :: Effect (ReactComponent { label :: String })
mkToggleButton = do
component "ToggleButton" \{ label } -> React.do
on /\ setOn <- useState false

useEffect on do
log $ "State: " <> if on then "On" else "Off"
pure (pure unit)

pure $ R.button
{ onClick: handler_ $ setOn not
, children:
[ R.text label
, R.text if on then " On" else " Off"
]
}
pure
$ R.button
{ onClick: handler_ $ setOn not
, children:
[ R.text label
, R.text if on then " On" else " Off"
]
}
8 changes: 4 additions & 4 deletions examples/context/src/Context.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import Prelude
import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (type (/\), CreateComponent, JSX, ReactContext, component, createContext, element, provider, useContext, useState, (/\))
import React.Basic.Hooks (type (/\), ReactComponent, JSX, ReactContext, component, createContext, element, provider, useContext, useState, (/\))
import React.Basic.Hooks as React

mkContext :: CreateComponent {}
mkContext :: Effect (ReactComponent {})
mkContext = do
counterContext <- createContext (0 /\ pure unit)
store <- mkStore counterContext
Expand All @@ -24,7 +24,7 @@ mkContext = do

mkStore ::
ReactContext (Int /\ (Effect Unit)) ->
CreateComponent { children :: Array JSX }
Effect (ReactComponent { children :: Array JSX })
mkStore context = do
component "Store" \{ children } -> React.do
counter /\ setCounter <- useState 0
Expand All @@ -37,7 +37,7 @@ mkStore context = do

mkCounter ::
ReactContext (Int /\ (Effect Unit)) ->
CreateComponent {}
Effect (ReactComponent {})
mkCounter counterContext = do
component "Counter" \props -> React.do
counter /\ increment <- useContext counterContext
Expand Down
58 changes: 29 additions & 29 deletions examples/controlled-input/src/ControlledInput.purs
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
module ControlledInput where

import Prelude

import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.DOM.Events (preventDefault, stopPropagation, targetValue, timeStamp)
import React.Basic.Events (EventHandler, handler, merge)
import React.Basic.Hooks (CreateComponent, UseState, Hook, component, fragment, useState, (/\))
import React.Basic.Hooks (ReactComponent, UseState, Hook, component, fragment, useState, (/\))
import React.Basic.Hooks as React

mkControlledInput :: CreateComponent {}
mkControlledInput :: Effect (ReactComponent {})
mkControlledInput = do
component "ControlledInput" \props -> React.do
firstName <- useInput "hello"
lastName <- useInput "world"

pure $ R.form_
[ renderInput firstName
, renderInput lastName
]
pure
$ R.form_
[ renderInput firstName
, renderInput lastName
]
where
renderInput input =
fragment
[ R.input { onChange: input.onChange, value: input.value }
, R.p_ [ R.text ("Current value = " <> show input.value) ]
, R.p_ [ R.text ("Changed at = " <> maybe "never" show input.lastChanged) ]
]
renderInput input =
fragment
[ R.input { onChange: input.onChange, value: input.value }
, R.p_ [ R.text ("Current value = " <> show input.value) ]
, R.p_ [ R.text ("Changed at = " <> maybe "never" show input.lastChanged) ]
]

useInput
:: String
-> Hook
(UseState { value :: String, lastChanged :: Maybe Number })
{ onChange :: EventHandler
, value :: String
, lastChanged :: Maybe Number
}
useInput ::
String ->
Hook
(UseState { value :: String, lastChanged :: Maybe Number })
{ onChange :: EventHandler
, value :: String
, lastChanged :: Maybe Number
}
useInput initialValue = React.do
{ value, lastChanged } /\ replaceState <- useState { value: initialValue, lastChanged: Nothing }
pure
{ onChange: handler
(preventDefault >>> stopPropagation >>> merge { targetValue, timeStamp })
\{ timeStamp, targetValue } -> do
replaceState \_ ->
{ value: fromMaybe "" targetValue
, lastChanged: Just timeStamp
}
{ onChange:
handler
(preventDefault >>> stopPropagation >>> merge { targetValue, timeStamp }) \{ timeStamp, targetValue } -> do
replaceState \_ ->
{ value: fromMaybe "" targetValue
, lastChanged: Just timeStamp
}
, value
, lastChanged
}
20 changes: 9 additions & 11 deletions examples/counter/src/Counter.purs
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
module Counter where

import Prelude

import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (CreateComponent, component, fragment, useEffect, useState, (/\))
import React.Basic.Hooks (ReactComponent, component, fragment, useEffect, useState, (/\))
import React.Basic.Hooks as React

mkCounter :: CreateComponent {}
mkCounter :: Effect (ReactComponent {})
mkCounter = do
component "Counter" \props -> React.do
counter /\ setCounter <- useState 0

useEffect counter do
setDocumentTitle $ "Count: " <> show counter
pure mempty

pure $ fragment
[ R.button
{ onClick: handler_ $ setCounter (_ + 1)
, children: [ R.text $ "Increment: " <> show counter ]
}
]
pure
$ fragment
[ R.button
{ onClick: handler_ $ setCounter (_ + 1)
, children: [ R.text $ "Increment: " <> show counter ]
}
]

foreign import setDocumentTitle :: String -> Effect Unit
26 changes: 13 additions & 13 deletions examples/memo-callback/src/MemoCallback.purs
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
module MemoCallback where

import Prelude

import Effect (Effect)
import Effect.Console (log)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (CreateComponent, UnsafeReference(..), component, fragment, useCallback, useEffect, useState, (/\))
import React.Basic.Hooks (ReactComponent, UnsafeReference(..), component, fragment, useCallback, useEffect, useState, (/\))
import React.Basic.Hooks as React

mkMemoCallback :: CreateComponent {}
mkMemoCallback :: Effect (ReactComponent {})
mkMemoCallback = do
component "MemoCallback" \props -> React.do
counter /\ setCounter <- useState 0
increment <- useCallback (UnsafeReference setCounter) $
setCounter (_ + 1)

increment <-
useCallback (UnsafeReference setCounter)
$ setCounter (_ + 1)
useEffect (UnsafeReference increment) do
log "increment updated"
pure mempty

pure $ fragment
[ R.button
{ onClick: handler_ increment
, children: [ R.text $ "Increment: " <> show counter ]
}
]
pure
$ fragment
[ R.button
{ onClick: handler_ increment
, children: [ R.text $ "Increment: " <> show counter ]
}
]
33 changes: 16 additions & 17 deletions examples/reducer/src/Reducer.purs
Original file line number Diff line number Diff line change
@@ -1,35 +1,34 @@
module Reducer where

import Prelude

import Effect (Effect)
import React.Basic.DOM as R
import React.Basic.Events (handler_)
import React.Basic.Hooks (CreateComponent, component, fragment, useReducer, (/\))
import React.Basic.Hooks (ReactComponent, component, fragment, useReducer, (/\))
import React.Basic.Hooks as React

data Action
= Increment
| Decrement

mkReducer :: CreateComponent {}
mkReducer :: Effect (ReactComponent {})
mkReducer = do
component "Reducer" \props -> React.do

state /\ dispatch <-
useReducer { counter: 0 } \state -> case _ of
Increment -> state { counter = state.counter + 1 }
Decrement -> state { counter = state.counter - 1 }

pure $ fragment
[ R.button
{ onClick: handler_ $ dispatch Decrement
, children: [ R.text $ "Decrement" ]
}
, R.button
{ onClick: handler_ $ dispatch Increment
, children: [ R.text $ "Increment" ]
}
, R.div_
[ R.text $ show state.counter
pure
$ fragment
[ R.button
{ onClick: handler_ $ dispatch Decrement
, children: [ R.text $ "Decrement" ]
}
, R.button
{ onClick: handler_ $ dispatch Increment
, children: [ R.text $ "Increment" ]
}
, R.div_
[ R.text $ show state.counter
]
]
]
Loading