Skip to content

Commit 9eab8c7

Browse files
committed
More robust state/props handling
Allowing for container components to include props passed from the parent component in conjunction with the store's state to obtain the final props for the component.
1 parent 767a1ae commit 9eab8c7

File tree

2 files changed

+59
-25
lines changed

2 files changed

+59
-25
lines changed

src/React/Redux.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@ var Redux = require('redux');
44

55
var ReactRedux = require('react-redux');
66

7+
var actionType = '@@PURESCRIPT_REACT_REDUX';
8+
9+
function startsWithActionType(actionForeign) {
10+
var index = actionForeign.type.indexOf(actionType);
11+
12+
return index === 0;
13+
}
14+
715
function makeActionForeign(action) {
16+
var constructorName = action.constructor && action.constructor.name ? action.constructor.name : 'UnknownConstructorName';
17+
818
var actionForeign = {
9-
type: '@@purescript',
19+
type: actionType + '/' + constructorName,
1020
action: action
1121
};
1222

@@ -16,9 +26,7 @@ function makeActionForeign(action) {
1626
exports.createStore_ = function createStore_(reducer, state, enhancer){
1727
return function(){
1828
function reducerForeign(stateReducerForeign, actionForeign){
19-
var action = actionForeign.action;
20-
21-
var result = action === undefined ? stateReducerForeign : reducer(action)(stateReducerForeign);
29+
var result = startsWithActionType(actionForeign) ? reducer(actionForeign.action)(stateReducerForeign) : stateReducerForeign;
2230

2331
return result;
2432
}
@@ -43,8 +51,16 @@ exports.createStore_ = function createStore_(reducer, state, enhancer){
4351
};
4452
};
4553

46-
exports.connect = function connect(stateToProps){
47-
return ReactRedux.connect(stateToProps);
54+
exports.connect_ = function connect_(Tuple, mapStateToProps, reactClass){
55+
function mapStateToPropsForeign(state, props) {
56+
var statePropsTuple = Tuple(state)(props);
57+
58+
var result = mapStateToProps(statePropsTuple);
59+
60+
return result;
61+
}
62+
63+
return ReactRedux.connect(mapStateToPropsForeign)(reactClass);
4864
};
4965

5066
exports.dispatch_ = function dispatch_(thisForeign, action){

src/React/Redux.purs

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module React.Redux
22
( ReduxReactClass
3+
, ReduxReactClass'
34
, ReduxEffect
45
, REDUX
56
, Reducer
@@ -20,8 +21,10 @@ module React.Redux
2021
, ComponentDidUpdate
2122
, ComponentWillUnmount
2223
, createClass
24+
, createClass'
2325
, createProviderElement
2426
, createElement
27+
, createElement'
2528
, createStore
2629
, createStore'
2730
, reducerOptic
@@ -31,19 +34,22 @@ module React.Redux
3134
, fromEnhancerForeign
3235
) where
3336

34-
import Prelude (Unit, (>>=), (<$), const, pure, id, unit)
37+
import Prelude (Unit, (>>=), (<<<), const, pure, id, unit)
3538

3639
import Control.Monad.Eff (Eff)
3740
import Control.Monad.Eff.Class (class MonadEff, liftEff)
3841

3942
import Data.Either (Either, either)
4043
import Data.Function.Uncurried (Fn2, Fn3, runFn2, runFn3)
41-
import Data.Lens (Getter', Lens', Prism', matching, set, view)
44+
import Data.Lens (Getter', Lens', Prism', matching, set, to, view)
45+
import Data.Tuple (Tuple(..), fst)
4246

4347
import Unsafe.Coerce (unsafeCoerce)
4448

4549
import React as React
4650

51+
type ReduxReactClass' state props = ReduxReactClass state Unit props
52+
4753
type Reducer action state = action -> state -> state
4854

4955
type ReducerForeign action state = Fn2 action state state
@@ -106,10 +112,13 @@ spec getInitialState render =
106112
spec' :: forall props eff f action. Render props Unit eff f action -> Spec props Unit eff f action
107113
spec' = spec (\_ _ -> pure unit)
108114

109-
createClass :: forall props state eff f action action' state'. MonadEff (ReduxEffect eff) f => Getter' action' action -> Getter' state' props -> Spec props state eff f action' -> ReduxReactClass state' props
110-
createClass actionLens stateLens spec_ = connect (view stateLens) reactClass
115+
createProviderElement :: forall action props state. Store action state -> ReduxReactClass' state props -> React.ReactElement
116+
createProviderElement store reduxClass = React.createElement providerClass { store: store } [ createElement' reduxClass [] ]
117+
118+
createClass :: forall eff f action props props' state state'. MonadEff (ReduxEffect eff) f => Getter' (Tuple state props) props' -> Spec props' state' eff f action -> ReduxReactClass state props props'
119+
createClass slens spec_ = runFn3 connect_ Tuple (view slens) reactClass
111120
where
112-
reactClass :: React.ReactClass props
121+
reactClass :: React.ReactClass props'
113122
reactClass =
114123
React.createClass { render: \this -> spec_.render (dispatch this) this
115124
, displayName: spec_.displayName
@@ -123,20 +132,29 @@ createClass actionLens stateLens spec_ = connect (view stateLens) reactClass
123132
, componentWillUnmount: \this -> spec_.componentWillUnmount (dispatch this) this
124133
}
125134
where
126-
dispatch :: React.ReactThis props state -> f action' -> f action'
127-
dispatch this action' = action' >>= \a -> a <$ liftEff (runFn2 dispatch_ this (view actionLens a))
135+
dispatch :: React.ReactThis props' state' -> f action -> f action
136+
dispatch this action = action >>= liftEff <<< runFn2 dispatch_ this
128137

129-
createProviderElement :: forall props action state'. Store action state' -> ReduxReactClass state' props -> React.ReactElement
130-
createProviderElement store reduxClass = React.createElement providerClass { store: store } [ createElement reduxClass ]
138+
createClass' :: forall eff f action props state. MonadEff (ReduxEffect eff) f => Getter' state props -> Spec props Unit eff f action -> ReduxReactClass' state props
139+
createClass' slens spec_ = createClass slens' spec_
140+
where
141+
slens' :: Getter' (Tuple state Unit) props
142+
slens' = to (view slens <<< fst)
143+
144+
createElement :: forall state props props'. ReduxReactClass state props props' -> props -> Array React.ReactElement -> React.ReactElement
145+
createElement reduxClass = React.createElement reactClass
146+
where
147+
reactClass :: React.ReactClass props
148+
reactClass = unsafeCoerce reduxClass
131149

132-
createElement :: forall props state'. ReduxReactClass state' props -> React.ReactElement
133-
createElement reduxClass = React.createElement (unsafeCoerce reduxClass) (unsafeCoerce unit) []
150+
createElement' :: forall state props. ReduxReactClass' state props -> Array React.ReactElement -> React.ReactElement
151+
createElement' reduxClass = createElement reduxClass unit
134152

135-
createStore :: forall eff action state. Reducer action state -> state -> Eff (ReduxEffect eff) (Store action state)
136-
createStore reducer state = createStore' reducer state id
153+
createStore :: forall eff action state. Reducer action state -> state -> Enhancer eff action state -> Eff (ReduxEffect eff) (Store action state)
154+
createStore = runFn3 createStore_
137155

138-
createStore' :: forall eff action state. Reducer action state -> state -> Enhancer eff action state -> Eff (ReduxEffect eff) (Store action state)
139-
createStore' = runFn3 createStore_
156+
createStore' :: forall eff action state. Reducer action state -> state -> Eff (ReduxEffect eff) (Store action state)
157+
createStore' reducer state = createStore reducer state id
140158

141159
reducerOptic :: forall state state' action action'. Lens' state state' -> Prism' action action' -> Reducer action' state' -> Reducer action state
142160
reducerOptic lens prism k action state = either (const state) (\a -> set lens (k a state') state) action'
@@ -151,13 +169,13 @@ foreign import data REDUX :: !
151169

152170
foreign import data Store :: * -> * -> *
153171

154-
foreign import data ReduxReactClass :: * -> * -> *
172+
foreign import data ReduxReactClass :: * -> * -> * -> *
155173

156-
foreign import connect :: forall state' props. (state' -> props) -> React.ReactClass props -> ReduxReactClass state' props
174+
foreign import connect_ :: forall state props props'. Fn3 (state -> props -> Tuple state props) (Tuple state props -> props') (React.ReactClass props') (ReduxReactClass state props props')
157175

158-
foreign import dispatch_ :: forall eff props action state. Fn2 (React.ReactThis props state) action (Eff (ReduxEffect eff) action)
176+
foreign import dispatch_ :: forall eff action props state. Fn2 (React.ReactThis props state) action (Eff (ReduxEffect eff) action)
159177

160-
foreign import providerClass :: forall action state'. React.ReactClass { store :: Store action state' }
178+
foreign import providerClass :: forall action state. React.ReactClass { store :: Store action state }
161179

162180
foreign import createStore_ :: forall eff action state. Fn3 (Reducer action state) state (Enhancer eff action state) (Eff (ReduxEffect eff) (Store action state))
163181

0 commit comments

Comments
 (0)