Skip to content

Commit 0fd12a5

Browse files
committed
Merge pull request #1 from ethul/topic/implementation
Initial implementation
2 parents e22bc0f + a193ca6 commit 0fd12a5

File tree

6 files changed

+245
-3
lines changed

6 files changed

+245
-3
lines changed

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2016 Eric Thul
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a
4+
copy of this software and associated documentation files (the
5+
"Software"), in the Software without restriction, including without
6+
limitation the rights to use, copy, modify, merge, publish, distribute,
7+
sublicense, and/or sell copies of the Software, and to permit persons to
8+
whom the Software is furnished to do so, subject to the following
9+
conditions:
10+
11+
The above copyright notice and this permission notice shall be included
12+
in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# purescript-react-redux
2+
3+
A library for using [Redux with React](http://redux.js.org/docs/basics/UsageWithReact.html).
4+
5+
## Installation
6+
7+
```bash
8+
bower install --save purescript-react-redux
9+
```
10+
11+
## Example
12+
13+
Refer to the [purescript-react-redux-example](https://github.com/ethul/purescript-react-redux-example) for an example.

bower.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
{
22
"name": "purescript-react-redux",
3-
"private": true,
3+
"description": "PureScript library for using Redux with React",
4+
"keywords": [
5+
"purescript",
6+
"react",
7+
"redux"
8+
],
9+
"license": "MIT",
10+
"repository": {
11+
"type": "git",
12+
"url": "git://github.com/ethul/purescript-react-redux.git"
13+
},
414
"ignore": [
515
"*",
616
"!src/**/*"
7-
]
17+
],
18+
"dependencies": {
19+
"purescript-profunctor-lenses": "~0.5.4",
20+
"purescript-react": "~0.7.1"
21+
}
822
}

package.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,14 @@
22
"name": "purescript-react-redux",
33
"version": "0.1.0",
44
"private": true,
5-
"files": []
5+
"files": [],
6+
"scripts": {
7+
"psc:server": "psc-ide-server --port 4291 --debug",
8+
"psc:watch": "pscid -p 4291",
9+
"build": "pulp build --force"
10+
},
11+
"devDependencies": {
12+
"pscid": "^1.7.3",
13+
"purescript": "^0.8.5"
14+
}
615
}

src/React/Redux.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict';
2+
3+
// module React.Redux
4+
5+
var Redux = require('redux');
6+
7+
var ReactRedux = require('react-redux');
8+
9+
function createStore_(reducer, state) {
10+
return function(){
11+
function reducer_(state, action){
12+
var action_ = action.action;
13+
return action_ === undefined ? state : reducer(action_)(state);
14+
};
15+
16+
return Redux.createStore(reducer_, state);
17+
};
18+
}
19+
exports.createStore_ = createStore_;
20+
21+
function connect(stateToProps) {
22+
return ReactRedux.connect(stateToProps);
23+
}
24+
exports.connect = connect;
25+
26+
function dispatch_(this_, action){
27+
return function(){
28+
var action_ = {
29+
type: '@@purescript',
30+
action: action
31+
};
32+
33+
var result = this_.props.dispatch(action_);
34+
35+
return result.action;
36+
};
37+
}
38+
exports.dispatch_ = dispatch_;
39+
40+
exports.providerClass = ReactRedux.Provider;

src/React/Redux.purs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
module React.Redux
2+
( ReduxReactClass
3+
, Effects
4+
, REDUX
5+
, Reducer
6+
, Store
7+
, createClass
8+
, createElement
9+
, createStore
10+
, reducerOptic
11+
12+
, Spec
13+
, Render
14+
, GetInitialState
15+
, ComponentWillMount
16+
, ComponentDidMount
17+
, ComponentWillReceiveProps
18+
, ShouldComponentUpdate
19+
, ComponentWillUpdate
20+
, ComponentDidUpdate
21+
, ComponentWillUnmount
22+
, spec
23+
, spec'
24+
) where
25+
26+
import Prelude (Unit, (<<<), (>>=), const, pure, unit)
27+
28+
import Control.Monad.Eff (Eff)
29+
import Control.Monad.Eff.Class (class MonadEff, liftEff)
30+
31+
import Data.Either (Either, either)
32+
import Data.Function (Fn2, runFn2)
33+
import Data.Lens (GetterP, LensP, PrismP, matching, set, view)
34+
35+
import Unsafe.Coerce (unsafeCoerce)
36+
37+
import React as React
38+
39+
type Reducer action state = action -> state -> state
40+
41+
type Effects eff = (redux :: REDUX | eff)
42+
43+
type Render props state eff f action = (f action -> f action) -> React.Render props state eff
44+
45+
type GetInitialState props state eff f action = (f action -> f action) -> React.GetInitialState props state eff
46+
47+
type ComponentWillMount props state eff f action = (f action -> f action) -> React.ComponentWillMount props state eff
48+
49+
type ComponentDidMount props state eff f action = (f action -> f action) -> React.ComponentDidMount props state eff
50+
51+
type ComponentWillReceiveProps props state eff f action = (f action -> f action) -> React.ComponentWillReceiveProps props state eff
52+
53+
type ShouldComponentUpdate props state eff f action = (f action -> f action) -> React.ShouldComponentUpdate props state eff
54+
55+
type ComponentWillUpdate props state eff f action = (f action -> f action) -> React.ComponentWillUpdate props state eff
56+
57+
type ComponentDidUpdate props state eff f action = (f action -> f action) -> React.ComponentDidUpdate props state eff
58+
59+
type ComponentWillUnmount props state eff f action = (f action -> f action) -> React.ComponentWillUnmount props state eff
60+
61+
type Spec props state eff f action =
62+
{ render :: Render props state eff f action
63+
, displayName :: String
64+
, getInitialState :: GetInitialState props state eff f action
65+
, componentWillMount :: ComponentWillMount props state eff f action
66+
, componentDidMount :: ComponentDidMount props state eff f action
67+
, componentWillReceiveProps :: ComponentWillReceiveProps props state eff f action
68+
, shouldComponentUpdate :: ShouldComponentUpdate props state eff f action
69+
, componentWillUpdate :: ComponentWillUpdate props state eff f action
70+
, componentDidUpdate :: ComponentDidUpdate props state eff f action
71+
, componentWillUnmount :: ComponentWillUnmount props state eff f action
72+
}
73+
74+
spec ::
75+
forall props state eff f action.
76+
GetInitialState props state eff f action ->
77+
Render props state eff f action ->
78+
Spec props state eff f action
79+
spec getInitialState render =
80+
{ render: render
81+
, displayName: ""
82+
, getInitialState: getInitialState
83+
, componentWillMount: \_ _ -> pure unit
84+
, componentDidMount: \_ _ -> pure unit
85+
, componentWillReceiveProps: \_ _ _ -> pure unit
86+
, shouldComponentUpdate: \_ _ _ _ -> pure true
87+
, componentWillUpdate: \_ _ _ _ -> pure unit
88+
, componentDidUpdate: \_ _ _ _ -> pure unit
89+
, componentWillUnmount: \_ _ -> pure unit
90+
}
91+
92+
spec' :: forall props eff f action. Render props Unit eff f action -> Spec props Unit eff f action
93+
spec' = spec (\_ _ -> pure unit)
94+
95+
createClass :: forall props state eff f action state'. MonadEff (Effects eff) f => GetterP state' props -> Spec props state eff f action -> ReduxReactClass state' props
96+
createClass lens spec_ = connect (view lens) reactClass
97+
where
98+
reactClass :: React.ReactClass props
99+
reactClass =
100+
React.createClass { render: \this -> spec_.render (dispatch this) this
101+
, displayName: spec_.displayName
102+
, getInitialState: \this -> spec_.getInitialState (dispatch this) this
103+
, componentWillMount: \this -> spec_.componentWillMount (dispatch this) this
104+
, componentDidMount: \this -> spec_.componentDidMount (dispatch this) this
105+
, componentWillReceiveProps: \this -> spec_.componentWillReceiveProps (dispatch this) this
106+
, shouldComponentUpdate: \this -> spec_.shouldComponentUpdate (dispatch this) this
107+
, componentWillUpdate: \this -> spec_.componentWillUpdate (dispatch this) this
108+
, componentDidUpdate: \this -> spec_.componentDidUpdate (dispatch this) this
109+
, componentWillUnmount: \this -> spec_.componentWillUnmount (dispatch this) this
110+
}
111+
where
112+
dispatch :: React.ReactThis props state -> f action -> f action
113+
dispatch this action = action >>= liftEff <<< runFn2 dispatch_ this
114+
115+
createElement :: forall props action state'. Store action state' -> ReduxReactClass state' props -> React.ReactElement
116+
createElement store reduxClass =
117+
React.createElement providerClass { store: store } [ reduxEl ]
118+
where
119+
reduxEl :: React.ReactElement
120+
reduxEl = React.createElement (unsafeCoerce reduxClass) (unsafeCoerce unit) []
121+
122+
createStore :: forall eff action state. Reducer action state -> state -> Eff (Effects eff) (Store action state)
123+
createStore = runFn2 createStore_
124+
125+
reducerOptic :: forall state state' action action'. LensP state state' -> PrismP action action' -> Reducer action' state' -> Reducer action state
126+
reducerOptic lens prism k action state = either (const state) (\a -> set lens (k a state') state) action'
127+
where
128+
state' :: state'
129+
state' = view lens state
130+
131+
action' :: Either action action'
132+
action' = matching prism action
133+
134+
foreign import data REDUX :: !
135+
136+
foreign import data Store :: * -> * -> *
137+
138+
foreign import data ReduxReactClass :: * -> * -> *
139+
140+
foreign import connect :: forall state' props. (state' -> props) -> React.ReactClass props -> ReduxReactClass state' props
141+
142+
foreign import dispatch_ :: forall eff props action state. Fn2 (React.ReactThis props state) action (Eff (Effects eff) action)
143+
144+
foreign import providerClass :: forall action state'. React.ReactClass { store :: Store action state' }
145+
146+
foreign import createStore_ :: forall eff action state. Fn2 (Reducer action state) state (Eff (Effects eff) (Store action state))

0 commit comments

Comments
 (0)