Skip to content

Commit

Permalink
fix(Carpenter): fix dispatch function not having updated state and …
Browse files Browse the repository at this point in the history
…props when called from inside `
  • Loading branch information
arthurxavierx committed Sep 19, 2016
1 parent 03d5f6e commit 6f2c22c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
32 changes: 23 additions & 9 deletions src/Carpenter.purs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Carpenter
, Dispatcher
, EventHandler
, ActionHandler
, CarpenterEffects
, mockUpdate
) where

Expand All @@ -15,12 +16,13 @@ import React as React
import Control.Monad.Aff (launchAff, makeAff, Aff)
import Control.Monad.Aff.Unsafe (unsafeInterleaveAff)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff.Unsafe (unsafeInterleaveEff)

type CarpenterEffects eff = (props :: React.ReactProps, state :: React.ReactState React.ReadWrite | eff)

-- | General purpose event handler for React events.
type EventHandler = eff. Eff
( state :: React.ReactState React.ReadWrite
| eff) Unit
type EventHandler = eff. Eff (CarpenterEffects eff) Unit

-- | Handler for dispatches of actions.
-- | Useful when handling actions dispatched by child components, e.g.:
Expand All @@ -39,7 +41,7 @@ type Dispatcher action = action -> EventHandler
-- | Type synonym for the `yield` function which takes a function from the
-- | current state to the new state of the component and asynchronously
-- | updates it.
type Yielder state eff = (state -> state) -> Aff (state :: React.ReactState React.ReadWrite | eff) state
type Yielder state eff = (state -> state) -> Aff (CarpenterEffects eff) state

-- | Type synonym for an action handler which takes a `Yielder` supplied by
-- | React's internal rendering function, a `Dispatcher` used to dispatch
Expand All @@ -53,7 +55,7 @@ type Update state props action eff
-> action
-> props
-> state
-> Aff (state :: React.ReactState React.ReadWrite | eff) state
-> Aff (CarpenterEffects eff) state

-- | Type synonym for a pure render function which takes a `Dispatcher` supplied
-- | by React's internal rendering function and the current props and state for
Expand Down Expand Up @@ -82,8 +84,7 @@ spec' state action update render = (React.spec state (getReactRender update rend
props <- React.getProps this
state <- React.readState this
let yield = mkYielder this
let dispatch :: Dispatcher action
dispatch action = void $ unsafeInterleaveEff (launchAff (update yield dispatch action props state))
let dispatch = mkDispatcher this update yield
unsafeInterleaveEff (launchAff (update yield dispatch action props state))

-- | Generates an update function for testing with mock `yield` and `dispatch`
Expand All @@ -105,12 +106,25 @@ mkYielder this = \f ->
let new = f old
React.writeStateWithCallback this new (resolve new)

mkDispatcher
:: state props action eff
. React.ReactThis props state
-> Update state props action eff
-> Yielder state eff
-> Dispatcher action
mkDispatcher this update yield = dispatch
where
dispatch :: Dispatcher action
dispatch action = void $ unsafeInterleaveEff $ launchAff do
props <- liftEff $ React.getProps this
state <- liftEff $ React.readState this
update yield dispatch action props state

getReactRender :: state props action eff. Update state props action eff -> Render state props action -> React.Render props state eff
getReactRender update render this = do
props <- React.getProps this
state <- React.readState this
children <- React.getChildren this
let yield = mkYielder this
let dispatch :: Dispatcher action
dispatch action = void $ unsafeInterleaveEff (launchAff (update yield dispatch action props state))
let dispatch = mkDispatcher this update yield
pure $ render dispatch props state children
15 changes: 11 additions & 4 deletions src/Carpenter/Cedar.purs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ cedarSpec' action update render = reactSpec
props <- React.getProps this
state <- React.readState this
let yield = mkYielder this
let dispatch = mkDispatcher update props state yield
let dispatch = mkDispatcher this update yield
unsafeInterleaveEff (launchAff (update yield dispatch action props state))

-- | Creates an element of the specificed React class with initial state
Expand Down Expand Up @@ -162,11 +162,18 @@ mkYielder this = \f ->
let new = f old
React.writeStateWithCallback this new (resolve new)

mkDispatcher :: state action eff. Update state (CedarProps state action) action eff -> (CedarProps state action) -> state -> Yielder state eff -> Dispatcher action
mkDispatcher update props state yield = dispatch
mkDispatcher
:: state action eff
. React.ReactThis (CedarProps state action) state
-> Update state (CedarProps state action) action eff
-> Yielder state eff
-> Dispatcher action
mkDispatcher this update yield = dispatch
where
dispatch :: Dispatcher action
dispatch action = void $ unsafeInterleaveEff $ launchAff do
props <- liftEff $ React.getProps this
state <- liftEff $ React.readState this
new <- update yield dispatch action props state
liftEff $ case props.handler of
Capture f -> f action
Expand All @@ -184,5 +191,5 @@ getReactRender update render this = do
state <- React.readState this
children <- React.getChildren this
let yield = mkYielder this
let dispatch = mkDispatcher update props state yield
let dispatch = mkDispatcher this update yield
pure $ render dispatch props state children

0 comments on commit 6f2c22c

Please sign in to comment.