├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── example
├── app.js
├── bundle.js
├── components
│ ├── AddTodo.js
│ ├── Footer.js
│ ├── VisibleTodoList.js
│ └── store.js
└── index.html
├── index.js
├── lib
├── combineReducers.js
├── connect.js
├── createStore.js
└── polyfill.js
├── package.json
├── test
├── test-combineReducers.js
├── test-connect.js
└── test-createStore.js
└── tutorial
├── bundle-example1.js
├── bundle-example2.js
├── bundle-example3.js
├── bundle-example4.js
├── bundle-example5.js
├── bundle-example6.js
├── example0.js
├── example1-react-withoutClass.js
├── example1-react.js
├── example1.js
├── example2-react.js
├── example3-react.js
├── example4-react.js
├── example5-react.js
├── example6-react.js
├── index-example1-react-withoutClass.html
├── index-example2.html
├── index-example3.html
├── index-example4.html
├── index-example5.html
└── index-example6.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "5"
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | REDUX-ES5 LICENSE
3 | =================
4 |
5 | MIT License
6 |
7 | Copyright (c) [2016] [David Wee]
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in all
17 | copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/rook2pawn/redux-es5)
2 |
3 | redux-es5
4 | =========
5 |
6 | Redux, with just es5. Fully supports connect bindings to React.
7 |
8 | Intro
9 | =====
10 |
11 | See the [example](../master/example) directory for a fully separated component app backed with connect on the redux-es5 store.
12 |
13 | You can open the [the web page](../master/example/index.html) in your browser to see the application in action. Compiled with [browserify](https://github.com/substack/browserify)
14 |
15 | The [tutorial](../master/tutorial) directory has many examples
16 |
17 | * [tutorial/example0.js](../master/tutorial/example0.js) - shows a demonstration of the redux-es5 store with a manual overall reducer
18 | * [tutorial/example1.js](../master/tutorial/example1.js) - shows the same thing but utilizes the redux-es5 combineReducers
19 | * [tutorial/example1-react.js](../master/tutorial/example1-react.js) - shows the view layer as expressed as React without JSX while still rendering via fully fledged React Components utilizing [hyperx](https://github.com/substack/hyperx)
20 | * [tutorial/example1-react-withoutClass.js](../master/tutorial/example1-react-withoutClass.js) - same thing as example1-react but utilizing the polyfill equivalent for es6 extends.
21 | * [tutorial/example2-react.js](../master/tutorial/example2-react.js) - Adds clicking on an item to mark it as completed.
22 | * [tutorial/example3-react.js](../master/tutorial/example3-react.js) - Adds a filter to show All, show active, and show completed.
23 | * [tutorial/example4-react.js](../master/tutorial/example4-react.js) - Refactor demonstrating nested classes and presentational components.
24 | * [tutorial/example5-react.js](../master/tutorial/example5-react.js) - Refactor demonstrating more separation of container and presentational components.
25 | * [tutorial/example6-react.js](../master/tutorial/example6-react.js) - Demonstrates the connect binding. Currently supports React Components, more on the way.
26 |
27 | You can open the corresponding html pages (e.g. [tutorial/index-example4.html](../master/tutorial/index-example4.html) )in the tutorial to see it in action.
28 |
29 |
30 | Example
31 | =======
32 | *taken from [example/app.js](../master/example/app.js)*
33 |
34 | The [connect declaration](../master/example/components/store.js) is the link between redux-es5 storage that drives this view layer.
35 |
36 | var react = require('react')
37 | var reactdom = require('react-dom');
38 | var hyperx = require('hyperx')
39 | var hx = hyperx(react.createElement)
40 |
41 | var connect = require('./components/store').connect
42 | var AddTodo = require('./components/AddTodo')(connect)
43 | var VisibleTodoList = require('./components/VisibleTodoList')(connect)
44 | var Footer = require('./components/Footer')(connect)
45 |
46 | var TodoApp = react.createClass({
47 | render : function() {
48 | return hx`
49 | ${react.createElement(AddTodo)}
50 | ${react.createElement(VisibleTodoList)}
51 | Show ${' '}
52 | ${react.createElement(Footer)}
53 |
`
54 | }
55 | });
56 | reactdom.render(react.createElement(TodoApp),document.querySelector('#content'))
57 |
58 |
59 | Coverage
60 | ========
61 |
62 |
63 | STATUS
64 | ======
65 |
66 | * createStore
67 | * combineReducers
68 | * connect
69 |
70 |
71 | I like JSX, I like Webpack, I like Babel, and I like ES6
72 | --------------------------------------------------------
73 |
74 | Then this module is probably not for you! JSX, Webpack and Babel are really quite cool but there are some people
75 | who may not prefer this type of stack added onto thier Node development cycle.
76 |
77 | Why Do I want to use this?
78 | --------------------------
79 |
80 | This module is really aimed at people who would like to use Redux and React but without introducing a transpiler,
81 | transpiler configurations, Webpack, and those people who may not want to use JSX or particularly care for ES6.
82 |
83 | If you like using Browserify and regular ES5 this module is for you!
84 |
85 | CONTRIB
86 | =======
87 |
88 | Please!
89 |
90 | LICENSE
91 | =======
92 |
93 | MIT License
94 |
95 | Copyright (c) [2016] [David Wee]
96 |
97 | Permission is hereby granted, free of charge, to any person obtaining a copy
98 | of this software and associated documentation files (the "Software"), to deal
99 | in the Software without restriction, including without limitation the rights
100 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101 | copies of the Software, and to permit persons to whom the Software is
102 | furnished to do so, subject to the following conditions:
103 |
104 | The above copyright notice and this permission notice shall be included in all
105 | copies or substantial portions of the Software.
106 |
107 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
108 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
109 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
110 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
111 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
112 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
113 | SOFTWARE.
114 |
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | var react = require('react')
2 | var reactdom = require('react-dom');
3 | var hyperx = require('hyperx')
4 | var hx = hyperx(react.createElement)
5 |
6 | var connect = require('./components/store').connect
7 | var AddTodo = require('./components/AddTodo')(connect)
8 | var VisibleTodoList = require('./components/VisibleTodoList')(connect)
9 | var Footer = require('./components/Footer')(connect)
10 |
11 |
12 | var TodoApp = react.createClass({
13 | render : function() {
14 | return hx`
15 | ${react.createElement(AddTodo)}
16 | ${react.createElement(VisibleTodoList)}
17 | Show ${' '}
18 | ${react.createElement(Footer)}
19 |
`
20 | }
21 | });
22 | reactdom.render(react.createElement(TodoApp),document.querySelector('#content'))
23 |
--------------------------------------------------------------------------------
/example/components/AddTodo.js:
--------------------------------------------------------------------------------
1 | var react = require('react')
2 | var hyperx = require('hyperx')
3 | var hx = hyperx(react.createElement)
4 |
5 | var AddTodoComponent = function(connect) {
6 | var nextTodoId = 0;
7 | var myinput;
8 | var AddTodo = react.createClass({
9 | render: function() {
10 | var that = this;
11 | return hx`
12 |
15 | Add Todo
23 |
`
24 | }
25 | })
26 | AddTodo = connect(null, null)(AddTodo);
27 | return AddTodo
28 | }
29 | module.exports = exports = AddTodoComponent;
30 |
--------------------------------------------------------------------------------
/example/components/Footer.js:
--------------------------------------------------------------------------------
1 | var react = require('react')
2 | var hyperx = require('hyperx')
3 | var hx = hyperx(react.createElement)
4 |
5 | var FooterComponent = function(connect) {
6 | var Link = react.createClass({
7 | render: function() {
8 | var that = this;
9 | if (this.props.active) {
10 | return hx`${this.props.children} `
11 | }
12 | return hx`${this.props.children} `;
16 | }
17 | })
18 | var FilterLink = connect(function(state,ownProps) {
19 | return {
20 | active : (ownProps.filter === state.visibilityFilter),
21 | children : ownProps.children
22 | }
23 | },function(dispatch,ownProps) {
24 | return {
25 | onClick: function() {
26 | dispatch({
27 | type:'SET_VISIBILITY_FILTER',
28 | filter:ownProps.filter
29 | })
30 | }
31 | }
32 | })(Link)
33 | var Footer = react.createClass({
34 | render: function() {
35 | return hx`${react.createElement(FilterLink,{filter:'SHOW_ALL',children:'All'})}
36 | ${react.createElement(FilterLink,{filter:'SHOW_ACTIVE',children:'Active'})}
37 | ${react.createElement(FilterLink,{filter:'SHOW_COMPLETED',children:'Completed'})}
`
38 | }
39 | })
40 | return Footer
41 | }
42 | module.exports = exports = FooterComponent;
43 |
--------------------------------------------------------------------------------
/example/components/VisibleTodoList.js:
--------------------------------------------------------------------------------
1 | var react = require('react')
2 | var hyperx = require('hyperx')
3 | var hx = hyperx(react.createElement)
4 |
5 | var VisibleTodoListComponent = function(connect) {
6 | var getVisibleTodos = function(todos,filter) {
7 | switch (filter) {
8 | case 'SHOW_ALL' :
9 | return todos
10 | case 'SHOW_COMPLETED' :
11 | return todos.filter(function(t) { return t.completed })
12 | case 'SHOW_ACTIVE' :
13 | return todos.filter(function(t) { return !t.completed })
14 | default:
15 | break;
16 | }
17 | }
18 | var Todo = react.createClass({
19 | render: function() {
20 | var that = this;
21 | return hx`${this.props.text} `
23 | }
24 | })
25 | var TodoList = react.createClass({
26 | render: function() {
27 | var that = this;
28 | return hx`
29 | ${this.props.todos.map(function(todo) {
30 | return react.createElement(Todo,{
31 | onClick:function() {
32 | that.props.onTodoClick(todo.id);
33 | },
34 | completed:todo.completed,
35 | text:todo.text
36 | })
37 | })}
38 | `
39 | }
40 | })
41 | var mapStateToProps = function(state) {
42 | return {
43 | todos: getVisibleTodos(state.todos,state.visibilityFilter)
44 | }
45 | }
46 | var mapDispatchToProps = function(dispatch) {
47 | return {
48 | onTodoClick: function(id) {
49 | dispatch({
50 | type:'TOGGLE_TODO',
51 | id:id
52 | })
53 | }
54 | }
55 | }
56 | var VisibleTodoList = connect(mapStateToProps,mapDispatchToProps)(TodoList)
57 | return VisibleTodoList
58 | }
59 | module.exports = exports = VisibleTodoListComponent;
60 |
--------------------------------------------------------------------------------
/example/components/store.js:
--------------------------------------------------------------------------------
1 | var redux = require('../../')
2 | var createStore = redux.createStore;
3 | var todo = function(state,action) {
4 | switch (action.type) {
5 | case 'ADD_TODO' :
6 | return {
7 | id: action.id,
8 | text: action.text,
9 | completed:false
10 | }
11 | break;
12 | case 'TOGGLE_TODO' :
13 | if (state.id !== action.id) {
14 | return state
15 | }
16 | return {
17 | type: state.type,
18 | id : state.id,
19 | text: state.text,
20 | completed: !state.completed
21 | }
22 | break;
23 | default:
24 | return state
25 | break;
26 | }
27 | }
28 | var todos = function(state, action) {
29 | if (state === undefined)
30 | state = []
31 | switch (action.type) {
32 | case 'ADD_TODO':
33 | return state.concat(todo(undefined,action))
34 | break;
35 | case 'TOGGLE_TODO' :
36 | return state.map(function(t) {
37 | return todo(t,action)
38 | })
39 | break;
40 | default:
41 | return state;
42 | }
43 | }
44 |
45 | var visibilityFilter = function(state, action) {
46 | if (state === undefined)
47 | state = 'SHOW_ALL'
48 | switch (action.type) {
49 | case 'SET_VISIBILITY_FILTER':
50 | return action.filter;
51 | break;
52 | default:
53 | return state
54 | }
55 | }
56 |
57 | var combineReducers = redux.combineReducers;
58 | var todoApp = combineReducers({
59 | todos:todos,
60 | visibilityFilter:visibilityFilter
61 | });
62 | var store = createStore(todoApp)
63 | var connect = redux.connect(store)
64 | exports.store = store;
65 | exports.connect = connect;
66 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | exports.createStore = require('./lib/createStore')
2 | exports.combineReducers = require('./lib/combineReducers')
3 | exports.connect = require('./lib/connect')
4 | exports.polyfill = require('./lib/polyfill')
5 |
--------------------------------------------------------------------------------
/lib/combineReducers.js:
--------------------------------------------------------------------------------
1 | var combineReducers = function(reducers) {
2 | return function(state,action) {
3 | if (state == undefined) {
4 | state = {}
5 | }
6 | return Object.keys(reducers)
7 | .reduce(function(nextState,key) {
8 | nextState[key] = reducers[key](state[key],action)
9 | return nextState;
10 | },{})
11 | }
12 | }
13 | module.exports = exports = combineReducers;
14 |
--------------------------------------------------------------------------------
/lib/connect.js:
--------------------------------------------------------------------------------
1 | var react = require('react')
2 | var objectAssign = require('object-assign')
3 | var hyperx = require('hyperx')
4 | var hx = hyperx(react.createElement)
5 | var connect = function(store) {
6 | if (!store) {
7 | throw new Error("Store is undefined")
8 | }
9 | return function(mapStateToProps,mapDispatchToProps) {
10 | return function(component) {
11 | var hasSubscribed = false;
12 | return react.createClass({
13 | componentDidMount:function() {
14 | var that = this;
15 | this.unsubscribe = store.subscribe(function() {
16 | that.forceUpdate()
17 | })
18 | },
19 | comonentWillUnmount:function() {
20 | this.unsubscribe();
21 | },
22 | render:function() {
23 | // this could be a candidate for optimization
24 | var state = store.getState();
25 | var ownProps = this.props;
26 | var _props1 = {};
27 | var _props2 = {};
28 | if (mapStateToProps)
29 | _props1 = mapStateToProps(state,ownProps);
30 | if (mapDispatchToProps)
31 | _props2 = mapDispatchToProps(store.dispatch,ownProps);
32 | else
33 | _props2 = { dispatch : store.dispatch }
34 | var props = objectAssign(_props1,_props2)
35 | if ((mapStateToProps) && (hasSubscribed === false)) {
36 | store.subscribe(function() {
37 | var state = store.getState();
38 | var _props1 = mapStateToProps(state,ownProps);
39 | props = objectAssign(_props1,_props2)
40 | })
41 | hasSubscribed = true;
42 | }
43 | return hx`${react.createElement(component,props)}`
44 | }
45 | })
46 | }
47 | }
48 | }
49 | module.exports = exports = connect;
50 |
--------------------------------------------------------------------------------
/lib/createStore.js:
--------------------------------------------------------------------------------
1 | var combineReducers = function(reducers) {
2 | return function(state,action) {
3 | if (state == undefined) {
4 | state = {}
5 | }
6 | return Object.keys(reducers)
7 | .reduce(function(nextState,key) {
8 | nextState[key] = reducers[key](state[key],action)
9 | return nextState;
10 | },{})
11 | }
12 | }
13 | exports.combineReducers = combineReducers;
14 |
15 | var createStore = function(reducer) {
16 | var state;
17 | var listeners = [];
18 | var getState = function () {
19 | return state
20 | }
21 | var dispatch = function(action) {
22 | //console.log('action:', action)
23 | state = reducer(state,action)
24 | //console.log("New state:", state)
25 | listeners.forEach(function(listener) {
26 | listener();
27 | })
28 | }
29 | var subscribe = function(listener) {
30 | listeners.push(listener)
31 | }
32 | dispatch({})
33 | return {getState:getState,dispatch:dispatch,subscribe:subscribe}
34 | }
35 | module.exports = exports = createStore;
36 |
--------------------------------------------------------------------------------
/lib/polyfill.js:
--------------------------------------------------------------------------------
1 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
2 | var object_assign = function (target) {
3 | if (target === undefined || target === null) {
4 | throw new TypeError('Cannot convert undefined or null to object');
5 | }
6 | var output = Object(target);
7 | for (var index = 1; index < arguments.length; index++) {
8 | var source = arguments[index];
9 | if (source !== undefined && source !== null) {
10 | for (var nextKey in source) {
11 | if (source.hasOwnProperty(nextKey)) {
12 | output[nextKey] = source[nextKey];
13 | }
14 | }
15 | }
16 | }
17 | return output;
18 | };
19 |
20 | exports.object = {
21 | assign : object_assign
22 | }
23 | exports.fill = function() {
24 | if (typeof Object.assign != 'function') {
25 | Object.assign = object_assign;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "redux-es5",
3 | "author": "David Wee (http://rook2pawn.com)",
4 | "version": "1.1.3",
5 | "description": "redux es5",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "tape $(find test -name '*.js')"
9 | },
10 | "keywords" : ["redux", "react", "es5", "hyperx", "jsx"],
11 | "license": "MIT",
12 | "devDependencies": {
13 | "deep-freeze": "0.0.1"
14 | },
15 | "dependencies": {
16 | "hyperx": "^2.0.3",
17 | "object-assign": "^4.1.0",
18 | "react": "^15.0.2",
19 | "tape": "^4.5.1"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/test/test-combineReducers.js:
--------------------------------------------------------------------------------
1 | var combineReducers = require('../lib/combineReducers')
2 | var deepFreeze = require('deep-freeze')
3 | var test = require('tape')
4 |
5 | test('combine reducer gives default state', function(t) {
6 | t.plan(1);
7 | var reducer = function(state,action) {
8 | if (state === undefined) {
9 | state = []
10 | }
11 | switch (action.type) {
12 | default:
13 | return state;
14 | break;
15 | }
16 | };
17 | var reducer2 = function(state,action) {
18 | if (state === undefined) {
19 | state = 0
20 | }
21 | switch (action.type) {
22 | default:
23 | return state;
24 | break;
25 | }
26 | };
27 | var app = combineReducers({
28 | foo : reducer,
29 | bar : reducer2
30 | });
31 | var stateBefore = {foo:undefined,bar:undefined};
32 | var action = {};
33 | var stateAfter = {foo:[],bar:0};
34 | deepFreeze(stateBefore)
35 | deepFreeze(action)
36 |
37 | t.deepEquals(app(stateBefore, action),stateAfter)
38 | })
39 | test('combine reducer follows a non default action', function(t) {
40 | t.plan(2);
41 | var reducer = function(state,action) {
42 | if (state === undefined) {
43 | state = []
44 | }
45 | switch (action.type) {
46 | case 'ADD_ITEM' :
47 | return state.concat(action.item)
48 | break;
49 | case 'INCR_ITEM' :
50 | return state
51 | .slice(0,action.id)
52 | .concat([state[action.id]+1])
53 | .concat(state.slice(action.id+1))
54 | break;
55 | default:
56 | return state;
57 | break;
58 | }
59 | }
60 | var app = combineReducers({
61 | foo : reducer
62 | })
63 |
64 | var stateBefore = {foo:undefined};
65 | var action = {type:'ADD_ITEM', item:4};
66 | var stateAfter = {foo:[4]};
67 | deepFreeze(stateBefore)
68 | deepFreeze(action)
69 | t.deepEquals(app(stateBefore,action), stateAfter);
70 |
71 |
72 | var stateBefore2 = {foo:[3,7,5,11,13]}
73 | var action2 = {type:'INCR_ITEM', id:3};
74 | var stateAfter2 = {foo:[3,7,5,12,13]};
75 | deepFreeze(stateBefore2)
76 | deepFreeze(action2)
77 | t.deepEquals(app(stateBefore2,action2), stateAfter2);
78 | })
79 |
--------------------------------------------------------------------------------
/test/test-connect.js:
--------------------------------------------------------------------------------
1 | var redux = require('../');
2 | var test = require('tape');
3 |
4 |
5 | test.skip('connect elementary test', function(t) {
6 | })
7 |
--------------------------------------------------------------------------------
/test/test-createStore.js:
--------------------------------------------------------------------------------
1 | var createStore = require('../lib/createStore');
2 | var combineReducers = require('../lib/combineReducers');
3 | var test = require('tape');
4 |
5 |
6 | test('check that store defers default state to the reducer', function(t) {
7 | t.plan(1)
8 | var reducer = function(state,action) {
9 | if (state === undefined) {
10 | state = []
11 | }
12 | switch (action.type) {
13 | default:
14 | return state;
15 | break;
16 | }
17 | }
18 | t.deepEquals(createStore(reducer).getState(),[])
19 | })
20 |
21 |
22 | test('getState - dispatch test', function(t) {
23 | t.plan(3)
24 | var reducer = function(state,action) {
25 | if (state === undefined) {
26 | state = []
27 | }
28 | switch (action.type) {
29 | case 'ADD_ITEM' :
30 | return state.concat([action.val])
31 | break;
32 | default:
33 | return state;
34 | break;
35 | }
36 | }
37 | var store = createStore(reducer);
38 | t.deepEquals(store.getState(),[])
39 | store.dispatch({type:'ADD_ITEM', val:3})
40 | t.deepEquals(store.getState(), [3])
41 | store.dispatch({type:'ADD_ITEM', val:5})
42 | t.deepEquals(store.getState(), [3,5])
43 | })
44 |
45 |
46 |
47 |
48 | test('getState - dispatch test with combineReducers', function(t) {
49 | var reducer = function(state,action) {
50 | if (state === undefined) {
51 | state = []
52 | }
53 | switch (action.type) {
54 | case 'ADD_ITEM' :
55 | return state.concat([action.val])
56 | break;
57 | default:
58 | return state;
59 | break;
60 | }
61 | }
62 | var reducer2 = function(state,action) {
63 | if (state === undefined) {
64 | state = 0
65 | }
66 | switch (action.type) {
67 | case 'INCR' :
68 | return state+1;
69 | break;
70 | case 'DOUBLE' :
71 | return state*2;
72 | break;
73 | default:
74 | return state;
75 | break;
76 | }
77 | }
78 | var store = createStore(combineReducers({list:reducer,number:reducer2}))
79 | t.deepEquals(store.getState(),{list:[],number:0})
80 | store.dispatch({type:'ADD_ITEM', val:3})
81 | store.dispatch({type:'ADD_ITEM', val:7})
82 | store.dispatch({type:'INCR'})
83 | store.dispatch({type:'INCR'})
84 | store.dispatch({type:'DOUBLE'})
85 | t.deepEquals(store.getState(),{list:[3,7],number:4})
86 | t.end()
87 | })
88 |
--------------------------------------------------------------------------------
/tutorial/example0.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 |
3 | var todo = function(state,action) {
4 | switch (action.type) {
5 | case 'ADD_TODO' :
6 | return {
7 | id: action.id,
8 | text: action.text,
9 | completed:false
10 | }
11 | break;
12 | case 'TOGGLE_TODO' :
13 | if (state.id !== action.id) {
14 | return state
15 | }
16 | return {
17 | type: state.type,
18 | id : state.id,
19 | text: state.text,
20 | completed: !state.completed
21 | }
22 | break;
23 | default:
24 | return state
25 | break;
26 | }
27 | }
28 | var todos = function(state, action) {
29 | if (state === undefined)
30 | state = []
31 | switch (action.type) {
32 | case 'ADD_TODO':
33 | return state.concat(todo(undefined,action))
34 | break;
35 | case 'TOGGLE_TODO' :
36 | return state.map(function(t) {
37 | return todo(t,action)
38 | })
39 | break;
40 | default:
41 | return state;
42 | }
43 | }
44 |
45 | var visibilityFilter = function(state, action) {
46 | if (state === undefined)
47 | state = 'SHOW_ALL'
48 | switch (action.type) {
49 | case 'SET_VISIBILITY_FILTER':
50 | return action.filter;
51 | break;
52 | default:
53 | return state
54 | }
55 | }
56 |
57 | var todoApp = function(state, action) {
58 | if (state === undefined)
59 | state = {}
60 | return {
61 | todos: todos(state.todos,action),
62 | visibilityFilter: visibilityFilter(state.visibilityFilter,action)
63 | }
64 | }
65 | var createStore = redux.createStore;
66 | var store = createStore(todoApp)
67 |
68 | console.log('Initial state:');
69 | console.log(store.getState());
70 | console.log('---------------')
71 |
72 | console.log('Dispatching ADD_TODO');
73 | store.dispatch({
74 | type:'ADD_TODO',
75 | id: 0,
76 | text:'Learn Redux'
77 | });
78 | console.log('Current state:');
79 | console.log(store.getState());
80 | console.log('---------------')
81 |
82 |
83 |
84 | console.log('Dispatching ADD_TODO');
85 | store.dispatch({
86 | type:'ADD_TODO',
87 | id: 1,
88 | text:'Go Shopping'
89 | });
90 | console.log('Current state:');
91 | console.log(store.getState());
92 | console.log('---------------')
93 |
94 |
95 |
96 | console.log('Dispatching TOGGLE_TODO');
97 | store.dispatch({
98 | type:'TOGGLE_TODO',
99 | id: 0
100 | });
101 | console.log('Current state:');
102 | console.log(store.getState());
103 | console.log('---------------')
104 |
105 |
106 | console.log('Dispatching SET_VISIBILITY_FILTER')
107 | store.dispatch({
108 | type:'SET_VISIBILITY_FILTER',
109 | filter:'SHOW_COMPLETED'
110 | });
111 | console.log('Current state:');
112 | console.log(store.getState());
113 | console.log('---------------')
114 |
--------------------------------------------------------------------------------
/tutorial/example1-react-withoutClass.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var todo = function(state,action) {
9 | switch (action.type) {
10 | case 'ADD_TODO' :
11 | return {
12 | id: action.id,
13 | text: action.text,
14 | completed:false
15 | }
16 | break;
17 | case 'TOGGLE_TODO' :
18 | if (state.id !== action.id) {
19 | return state
20 | }
21 | return {
22 | type: state.type,
23 | id : state.id,
24 | text: state.text,
25 | completed: !state.completed
26 | }
27 | break;
28 | default:
29 | return state
30 | break;
31 | }
32 | }
33 | var todos = function(state, action) {
34 | if (state === undefined)
35 | state = []
36 | switch (action.type) {
37 | case 'ADD_TODO':
38 | return state.concat(todo(undefined,action))
39 | break;
40 | case 'TOGGLE_TODO' :
41 | return state.map(function(t) {
42 | return todo(t,action)
43 | })
44 | break;
45 | default:
46 | return state;
47 | }
48 | }
49 |
50 | var visibilityFilter = function(state, action) {
51 | if (state === undefined)
52 | state = 'SHOW_ALL'
53 | switch (action.type) {
54 | case 'SET_VISIBILITY_FILTER':
55 | return action.filter;
56 | break;
57 | default:
58 | return state
59 | }
60 | }
61 |
62 | var combineReducers = redux.combineReducers;
63 | var todoApp = combineReducers({
64 | todos:todos,
65 | visibilityFilter:visibilityFilter
66 | });
67 | var createStore = redux.createStore;
68 | var store = createStore(todoApp)
69 | var Component = react.Component;
70 | var nextTodoId = 0;
71 | var myinput;
72 |
73 |
74 | var TodoApp = function() {
75 | Component.call(this);
76 | this.render = function() {
77 | return hx`
78 |
81 | Add Todo
89 |
90 |
91 | ${this.props.todos.map(function(todo) {
92 | return hx`${todo.text} `
93 | })}
94 |
95 |
`
96 | }
97 | }
98 | TodoApp.prototype = Object.create(Component.prototype);
99 | TodoApp.prototype.constructor = Component;
100 |
101 | var Factory = react.createFactory(TodoApp)
102 | var render = function() {
103 | var root = Factory({todos:store.getState().todos})
104 | reactdom.render(root, document.querySelector('#content'))
105 | }
106 | store.subscribe(render)
107 | render()
108 |
--------------------------------------------------------------------------------
/tutorial/example1-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var todo = function(state,action) {
9 | switch (action.type) {
10 | case 'ADD_TODO' :
11 | return {
12 | id: action.id,
13 | text: action.text,
14 | completed:false
15 | }
16 | break;
17 | case 'TOGGLE_TODO' :
18 | if (state.id !== action.id) {
19 | return state
20 | }
21 | return {
22 | type: state.type,
23 | id : state.id,
24 | text: state.text,
25 | completed: !state.completed
26 | }
27 | break;
28 | default:
29 | return state
30 | break;
31 | }
32 | }
33 | var todos = function(state, action) {
34 | if (state === undefined)
35 | state = []
36 | switch (action.type) {
37 | case 'ADD_TODO':
38 | return state.concat(todo(undefined,action))
39 | break;
40 | case 'TOGGLE_TODO' :
41 | return state.map(function(t) {
42 | return todo(t,action)
43 | })
44 | break;
45 | default:
46 | return state;
47 | }
48 | }
49 |
50 | var visibilityFilter = function(state, action) {
51 | if (state === undefined)
52 | state = 'SHOW_ALL'
53 | switch (action.type) {
54 | case 'SET_VISIBILITY_FILTER':
55 | return action.filter;
56 | break;
57 | default:
58 | return state
59 | }
60 | }
61 |
62 | var combineReducers = redux.combineReducers;
63 | var todoApp = combineReducers({
64 | todos:todos,
65 | visibilityFilter:visibilityFilter
66 | });
67 | var createStore = redux.createStore;
68 | var store = createStore(todoApp)
69 | var Component = react.Component;
70 | var nextTodoId = 0;
71 | var myinput;
72 |
73 | /*
74 | class TodoApp extends Component {
75 | render() {
76 | return hx`
77 |
80 | Add Todo
88 |
89 |
90 | ${this.props.todos.map(function(todo) {
91 | return hx`${todo.text} `
92 | })}
93 |
94 |
`
95 | }
96 | }
97 | */
98 | var Factory = react.createFactory(TodoApp)
99 | var render = function() {
100 | var root = Factory({todos:store.getState().todos})
101 | reactdom.render(root, document.querySelector('#content'))
102 | }
103 | store.subscribe(render)
104 | render()
105 |
--------------------------------------------------------------------------------
/tutorial/example1.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 |
3 | var todo = function(state,action) {
4 | switch (action.type) {
5 | case 'ADD_TODO' :
6 | return {
7 | id: action.id,
8 | text: action.text,
9 | completed:false
10 | }
11 | break;
12 | case 'TOGGLE_TODO' :
13 | if (state.id !== action.id) {
14 | return state
15 | }
16 | return {
17 | type: state.type,
18 | id : state.id,
19 | text: state.text,
20 | completed: !state.completed
21 | }
22 | break;
23 | default:
24 | return state
25 | break;
26 | }
27 | }
28 | var todos = function(state, action) {
29 | if (state === undefined)
30 | state = []
31 | switch (action.type) {
32 | case 'ADD_TODO':
33 | return state.concat(todo(undefined,action))
34 | break;
35 | case 'TOGGLE_TODO' :
36 | return state.map(function(t) {
37 | return todo(t,action)
38 | })
39 | break;
40 | default:
41 | return state;
42 | }
43 | }
44 |
45 | var visibilityFilter = function(state, action) {
46 | if (state === undefined)
47 | state = 'SHOW_ALL'
48 | switch (action.type) {
49 | case 'SET_VISIBILITY_FILTER':
50 | return action.filter;
51 | break;
52 | default:
53 | return state
54 | }
55 | }
56 |
57 | var combineReducers = redux.combineReducers;
58 | /*
59 | var todoApp = function(state, action) {
60 | if (state === undefined)
61 | state = {}
62 | return {
63 | todos: todos(state.todos,action),
64 | visibilityFilter: visibilityFilter(state.visibilityFilter,action)
65 | }
66 | }
67 | */
68 | var todoApp = combineReducers({
69 | todos:todos,
70 | visibilityFilter:visibilityFilter
71 | });
72 | var createStore = redux.createStore;
73 | var store = createStore(todoApp)
74 |
75 | console.log('Initial state:');
76 | console.log(store.getState());
77 | console.log('---------------')
78 |
79 | console.log('Dispatching ADD_TODO');
80 | store.dispatch({
81 | type:'ADD_TODO',
82 | id: 0,
83 | text:'Learn Redux'
84 | });
85 | console.log('Current state:');
86 | console.log(store.getState());
87 | console.log('---------------')
88 |
89 |
90 |
91 | console.log('Dispatching ADD_TODO');
92 | store.dispatch({
93 | type:'ADD_TODO',
94 | id: 1,
95 | text:'Go Shopping'
96 | });
97 | console.log('Current state:');
98 | console.log(store.getState());
99 | console.log('---------------')
100 |
101 |
102 |
103 | console.log('Dispatching TOGGLE_TODO');
104 | store.dispatch({
105 | type:'TOGGLE_TODO',
106 | id: 0
107 | });
108 | console.log('Current state:');
109 | console.log(store.getState());
110 | console.log('---------------')
111 |
112 |
113 | console.log('Dispatching SET_VISIBILITY_FILTER')
114 | store.dispatch({
115 | type:'SET_VISIBILITY_FILTER',
116 | filter:'SHOW_COMPLETED'
117 | });
118 | console.log('Current state:');
119 | console.log(store.getState());
120 | console.log('---------------')
121 |
--------------------------------------------------------------------------------
/tutorial/example2-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var todo = function(state,action) {
9 | switch (action.type) {
10 | case 'ADD_TODO' :
11 | return {
12 | id: action.id,
13 | text: action.text,
14 | completed:false
15 | }
16 | break;
17 | case 'TOGGLE_TODO' :
18 | if (state.id !== action.id) {
19 | return state
20 | }
21 | return {
22 | type: state.type,
23 | id : state.id,
24 | text: state.text,
25 | completed: !state.completed
26 | }
27 | break;
28 | default:
29 | return state
30 | break;
31 | }
32 | }
33 | var todos = function(state, action) {
34 | if (state === undefined)
35 | state = []
36 | switch (action.type) {
37 | case 'ADD_TODO':
38 | return state.concat(todo(undefined,action))
39 | break;
40 | case 'TOGGLE_TODO' :
41 | return state.map(function(t) {
42 | return todo(t,action)
43 | })
44 | break;
45 | default:
46 | return state;
47 | }
48 | }
49 |
50 | var visibilityFilter = function(state, action) {
51 | if (state === undefined)
52 | state = 'SHOW_ALL'
53 | switch (action.type) {
54 | case 'SET_VISIBILITY_FILTER':
55 | return action.filter;
56 | break;
57 | default:
58 | return state
59 | }
60 | }
61 |
62 | var combineReducers = redux.combineReducers;
63 | var todoApp = combineReducers({
64 | todos:todos,
65 | visibilityFilter:visibilityFilter
66 | });
67 | var createStore = redux.createStore;
68 | var store = createStore(todoApp)
69 | var Component = react.Component;
70 | var nextTodoId = 0;
71 | var myinput;
72 |
73 |
74 | var TodoApp = function() {
75 | Component.call(this);
76 | this.render = function() {
77 | return hx`
78 |
81 | Add Todo
89 |
90 |
91 | ${this.props.todos.map(function(todo) {
92 | return hx`${todo.text} `
98 | })}
99 |
100 |
`
101 | }
102 | }
103 | TodoApp.prototype = Object.create(Component.prototype);
104 | TodoApp.prototype.constructor = Component;
105 |
106 | var Factory = react.createFactory(TodoApp)
107 | var render = function() {
108 | var root = Factory({todos:store.getState().todos})
109 | reactdom.render(root, document.querySelector('#content'))
110 | }
111 | store.subscribe(render)
112 | render()
113 |
--------------------------------------------------------------------------------
/tutorial/example3-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var todo = function(state,action) {
9 | switch (action.type) {
10 | case 'ADD_TODO' :
11 | return {
12 | id: action.id,
13 | text: action.text,
14 | completed:false
15 | }
16 | break;
17 | case 'TOGGLE_TODO' :
18 | if (state.id !== action.id) {
19 | return state
20 | }
21 | return {
22 | type: state.type,
23 | id : state.id,
24 | text: state.text,
25 | completed: !state.completed
26 | }
27 | break;
28 | default:
29 | return state
30 | break;
31 | }
32 | }
33 | var todos = function(state, action) {
34 | if (state === undefined)
35 | state = []
36 | switch (action.type) {
37 | case 'ADD_TODO':
38 | return state.concat(todo(undefined,action))
39 | break;
40 | case 'TOGGLE_TODO' :
41 | return state.map(function(t) {
42 | return todo(t,action)
43 | })
44 | break;
45 | default:
46 | return state;
47 | }
48 | }
49 |
50 | var visibilityFilter = function(state, action) {
51 | if (state === undefined)
52 | state = 'SHOW_ALL'
53 | switch (action.type) {
54 | case 'SET_VISIBILITY_FILTER':
55 | return action.filter;
56 | break;
57 | default:
58 | return state
59 | }
60 | }
61 |
62 | var combineReducers = redux.combineReducers;
63 | var todoApp = combineReducers({
64 | todos:todos,
65 | visibilityFilter:visibilityFilter
66 | });
67 | var createStore = redux.createStore;
68 | var store = createStore(todoApp)
69 |
70 | var getVisibleTodos = function(todos,filter) {
71 | switch (filter) {
72 | case 'SHOW_ALL' :
73 | return todos
74 | case 'SHOW_COMPLETED' :
75 | return todos.filter(function(t) { return t.completed })
76 | case 'SHOW_ACTIVE' :
77 | return todos.filter(function(t) { return !t.completed })
78 | default:
79 | break;
80 | }
81 | }
82 | var FilterLink = react.createClass({
83 | render: function() {
84 | var that = this;
85 | if (this.props.filter === this.props.currentFilter) {
86 | return hx`${this.props.children} `
87 | }
88 | return hx`${this.props.children} `;
94 | }
95 | })
96 |
97 | var nextTodoId = 0;
98 | var myinput;
99 | var TodoApp = react.createClass({
100 | render : function() {
101 | var visibleTodos = getVisibleTodos(this.props.todos,this.props.visibilityFilter);
102 | return hx`
103 |
106 | Add Todo
114 |
115 |
116 | ${visibleTodos.map(function(todo) {
117 | return hx`${todo.text} `
123 | })}
124 |
125 | Show ${' '}
126 | ${react.createElement(FilterLink,{filter:'SHOW_ALL',children:'All',currentFilter:this.props.visibilityFilter})}
127 | ${react.createElement(FilterLink,{filter:'SHOW_ACTIVE',children:'Active',currentFilter:this.props.visibilityFilter})}
128 | ${react.createElement(FilterLink,{filter:'SHOW_COMPLETED',children:'Completed',currentFilter:this.props.visibilityFilter})}
129 |
`
130 | }
131 | });
132 |
133 | var render = function() {
134 | reactdom.render(react.createElement(TodoApp, {
135 | todos:store.getState().todos,
136 | visibilityFilter:store.getState().visibilityFilter
137 | }),document.querySelector('#content'))
138 | }
139 | store.subscribe(render)
140 | render()
141 |
--------------------------------------------------------------------------------
/tutorial/example4-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var nextTodoId = 0;
9 | var myinput;
10 |
11 | var todo = function(state,action) {
12 | switch (action.type) {
13 | case 'ADD_TODO' :
14 | return {
15 | id: action.id,
16 | text: action.text,
17 | completed:false
18 | }
19 | break;
20 | case 'TOGGLE_TODO' :
21 | if (state.id !== action.id) {
22 | return state
23 | }
24 | return {
25 | type: state.type,
26 | id : state.id,
27 | text: state.text,
28 | completed: !state.completed
29 | }
30 | break;
31 | default:
32 | return state
33 | break;
34 | }
35 | }
36 | var todos = function(state, action) {
37 | if (state === undefined)
38 | state = []
39 | switch (action.type) {
40 | case 'ADD_TODO':
41 | return state.concat(todo(undefined,action))
42 | break;
43 | case 'TOGGLE_TODO' :
44 | return state.map(function(t) {
45 | return todo(t,action)
46 | })
47 | break;
48 | default:
49 | return state;
50 | }
51 | }
52 |
53 | var visibilityFilter = function(state, action) {
54 | if (state === undefined)
55 | state = 'SHOW_ALL'
56 | switch (action.type) {
57 | case 'SET_VISIBILITY_FILTER':
58 | return action.filter;
59 | break;
60 | default:
61 | return state
62 | }
63 | }
64 |
65 | var combineReducers = redux.combineReducers;
66 | var todoApp = combineReducers({
67 | todos:todos,
68 | visibilityFilter:visibilityFilter
69 | });
70 | var createStore = redux.createStore;
71 | var store = createStore(todoApp)
72 |
73 | var getVisibleTodos = function(todos,filter) {
74 | switch (filter) {
75 | case 'SHOW_ALL' :
76 | return todos
77 | case 'SHOW_COMPLETED' :
78 | return todos.filter(function(t) { return t.completed })
79 | case 'SHOW_ACTIVE' :
80 | return todos.filter(function(t) { return !t.completed })
81 | default:
82 | break;
83 | }
84 | }
85 | var FilterLink = react.createClass({
86 | render: function() {
87 | var that = this;
88 | if (this.props.filter === this.props.currentFilter) {
89 | return hx`${this.props.children} `
90 | }
91 | return hx`${this.props.children} `;
95 | }
96 | })
97 |
98 |
99 | var Todo = react.createClass({
100 | render: function() {
101 | var that = this;
102 | return hx`${this.props.text} `
104 | }
105 | })
106 | var TodoList = react.createClass({
107 | render: function() {
108 | var that = this;
109 | return hx`
110 | ${this.props.todos.map(function(todo) {
111 | return react.createElement(Todo,{
112 | onClick:function() {
113 | that.props.onTodoClick(todo.id);
114 | },
115 | completed:todo.completed,
116 | text:todo.text
117 | })
118 | })}
119 | `
120 | }
121 | })
122 |
123 | var AddTodo = react.createClass({
124 | render: function() {
125 | var that = this;
126 | return hx`
127 |
130 | Add Todo
133 |
`
134 | }
135 | })
136 | var Footer = react.createClass({
137 | render: function() {
138 | return hx`${react.createElement(FilterLink,{filter:'SHOW_ALL',children:'All',currentFilter:this.props.visibilityFilter,onClick:this.props.onFilterClick})}
139 | ${react.createElement(FilterLink,{filter:'SHOW_ACTIVE',children:'Active',currentFilter:this.props.visibilityFilter,onClick:this.props.onFilterClick})}
140 | ${react.createElement(FilterLink,{filter:'SHOW_COMPLETED',children:'Completed',currentFilter:this.props.visibilityFilter,onClick:this.props.onFilterClick})}
`
141 | }
142 | })
143 |
144 | var TodoApp = react.createClass({
145 | render : function() {
146 | return hx`
147 | ${react.createElement(AddTodo,{
148 | onAddClick:function(text) {
149 | store.dispatch({
150 | type:'ADD_TODO',
151 | id:nextTodoId++,
152 | text:text
153 | })
154 | myinput.value='';
155 | }
156 | })}
157 | ${react.createElement(TodoList,{
158 | onTodoClick:function(id) {
159 | store.dispatch({
160 | type:'TOGGLE_TODO',
161 | id: id
162 | })
163 | },
164 | todos:getVisibleTodos(this.props.todos,this.props.visibilityFilter)
165 | })}
166 | Show ${' '}
167 | ${react.createElement(Footer,{
168 | onFilterClick: function(filter) {
169 | store.dispatch({
170 | type:'SET_VISIBILITY_FILTER',
171 | filter:filter
172 | })
173 | },
174 | visibilityFilter:this.props.visibilityFilter})}
175 |
`
176 | }
177 | });
178 |
179 | var render = function() {
180 | reactdom.render(react.createElement(TodoApp, {
181 | todos:store.getState().todos,
182 | visibilityFilter:store.getState().visibilityFilter
183 | }),document.querySelector('#content'))
184 | }
185 | store.subscribe(render)
186 | render()
187 |
--------------------------------------------------------------------------------
/tutorial/example5-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var toString = require('react-dom/server').renderToString;
4 | var reactdom = require('react-dom');
5 | var hyperx = require('hyperx')
6 | var hx = hyperx(react.createElement)
7 |
8 | var nextTodoId = 0;
9 | var myinput;
10 |
11 | var todo = function(state,action) {
12 | switch (action.type) {
13 | case 'ADD_TODO' :
14 | return {
15 | id: action.id,
16 | text: action.text,
17 | completed:false
18 | }
19 | break;
20 | case 'TOGGLE_TODO' :
21 | if (state.id !== action.id) {
22 | return state
23 | }
24 | return {
25 | type: state.type,
26 | id : state.id,
27 | text: state.text,
28 | completed: !state.completed
29 | }
30 | break;
31 | default:
32 | return state
33 | break;
34 | }
35 | }
36 | var todos = function(state, action) {
37 | if (state === undefined)
38 | state = []
39 | switch (action.type) {
40 | case 'ADD_TODO':
41 | return state.concat(todo(undefined,action))
42 | break;
43 | case 'TOGGLE_TODO' :
44 | return state.map(function(t) {
45 | return todo(t,action)
46 | })
47 | break;
48 | default:
49 | return state;
50 | }
51 | }
52 |
53 | var visibilityFilter = function(state, action) {
54 | if (state === undefined)
55 | state = 'SHOW_ALL'
56 | switch (action.type) {
57 | case 'SET_VISIBILITY_FILTER':
58 | return action.filter;
59 | break;
60 | default:
61 | return state
62 | }
63 | }
64 |
65 | var combineReducers = redux.combineReducers;
66 | var todoApp = combineReducers({
67 | todos:todos,
68 | visibilityFilter:visibilityFilter
69 | });
70 | var createStore = redux.createStore;
71 | var store = createStore(todoApp)
72 |
73 | var getVisibleTodos = function(todos,filter) {
74 | switch (filter) {
75 | case 'SHOW_ALL' :
76 | return todos
77 | case 'SHOW_COMPLETED' :
78 | return todos.filter(function(t) { return t.completed })
79 | case 'SHOW_ACTIVE' :
80 | return todos.filter(function(t) { return !t.completed })
81 | default:
82 | break;
83 | }
84 | }
85 | var Link = react.createClass({
86 | render: function() {
87 | var that = this;
88 | if (this.props.active) {
89 | return hx`${this.props.children} `
90 | }
91 | return hx`${this.props.children} `;
95 | }
96 | })
97 |
98 | var FilterLink = react.createClass({
99 | componentDidMount:function() {
100 | var that = this;
101 | this.unsubscribe = store.subscribe(function() {
102 | that.forceUpdate()
103 | })
104 | },
105 | comonentWillUnmount:function() {
106 | this.unsubscribe();
107 | },
108 | render: function() {
109 | var props = this.props;
110 | var state = store.getState();
111 | return hx`${react.createElement(Link, {
112 | active:(props.filter===state.visibilityFilter),
113 | onClick:function() {
114 | store.dispatch({
115 | type:'SET_VISIBILITY_FILTER',
116 | filter:props.filter
117 | })
118 | },
119 | children:props.children})}`
120 | }
121 | })
122 |
123 |
124 | var Todo = react.createClass({
125 | render: function() {
126 | var that = this;
127 | return hx`${this.props.text} `
129 | }
130 | })
131 | var TodoList = react.createClass({
132 | render: function() {
133 | var that = this;
134 | return hx`
135 | ${this.props.todos.map(function(todo) {
136 | return react.createElement(Todo,{
137 | onClick:function() {
138 | that.props.onTodoClick(todo.id);
139 | },
140 | completed:todo.completed,
141 | text:todo.text
142 | })
143 | })}
144 | `
145 | }
146 | })
147 |
148 | var AddTodo = react.createClass({
149 | render: function() {
150 | var that = this;
151 | return hx`
152 |
155 | Add Todo
166 |
`
167 | }
168 | })
169 | var Footer = react.createClass({
170 | render: function() {
171 | return hx`${react.createElement(FilterLink,{filter:'SHOW_ALL',children:'All'})}
172 | ${react.createElement(FilterLink,{filter:'SHOW_ACTIVE',children:'Active'})}
173 | ${react.createElement(FilterLink,{filter:'SHOW_COMPLETED',children:'Completed'})}
`
174 | }
175 | })
176 |
177 | var VisibleTodoList = react.createClass({
178 | componentDidMount:function() {
179 | var that = this;
180 | this.unsubscribe = store.subscribe(function() {
181 | that.forceUpdate()
182 | })
183 | },
184 | comonentWillUnmount:function() {
185 | this.unsubscribe();
186 | },
187 | render: function() {
188 | var props = this.props;
189 | var state = store.getState();
190 | return hx`${react.createElement(TodoList,{
191 | todos:getVisibleTodos(state.todos,state.visibilityFilter),
192 | onTodoClick:function(id) {
193 | store.dispatch({
194 | type:'TOGGLE_TODO',
195 | id:id
196 | })
197 | }})}`
198 | }
199 | })
200 |
201 | var TodoApp = react.createClass({
202 | render : function() {
203 | return hx`
204 | ${react.createElement(AddTodo)}
205 | ${react.createElement(VisibleTodoList)}
206 | Show ${' '}
207 | ${react.createElement(Footer)}
208 |
`
209 | }
210 | });
211 |
212 | reactdom.render(react.createElement(TodoApp),document.querySelector('#content'))
213 |
--------------------------------------------------------------------------------
/tutorial/example6-react.js:
--------------------------------------------------------------------------------
1 | var redux = require('../')
2 | var react = require('react')
3 | var reactdom = require('react-dom');
4 | var hyperx = require('hyperx')
5 | var hx = hyperx(react.createElement)
6 | var createStore = redux.createStore;
7 |
8 | var nextTodoId = 0;
9 | var myinput;
10 |
11 | var todo = function(state,action) {
12 | switch (action.type) {
13 | case 'ADD_TODO' :
14 | return {
15 | id: action.id,
16 | text: action.text,
17 | completed:false
18 | }
19 | break;
20 | case 'TOGGLE_TODO' :
21 | if (state.id !== action.id) {
22 | return state
23 | }
24 | return {
25 | type: state.type,
26 | id : state.id,
27 | text: state.text,
28 | completed: !state.completed
29 | }
30 | break;
31 | default:
32 | return state
33 | break;
34 | }
35 | }
36 | var todos = function(state, action) {
37 | if (state === undefined)
38 | state = []
39 | switch (action.type) {
40 | case 'ADD_TODO':
41 | return state.concat(todo(undefined,action))
42 | break;
43 | case 'TOGGLE_TODO' :
44 | return state.map(function(t) {
45 | return todo(t,action)
46 | })
47 | break;
48 | default:
49 | return state;
50 | }
51 | }
52 |
53 | var visibilityFilter = function(state, action) {
54 | if (state === undefined)
55 | state = 'SHOW_ALL'
56 | switch (action.type) {
57 | case 'SET_VISIBILITY_FILTER':
58 | return action.filter;
59 | break;
60 | default:
61 | return state
62 | }
63 | }
64 |
65 | var combineReducers = redux.combineReducers;
66 | var todoApp = combineReducers({
67 | todos:todos,
68 | visibilityFilter:visibilityFilter
69 | });
70 | var store = createStore(todoApp)
71 | // end of model layer
72 |
73 | //view layer
74 | var connect = redux.connect(store);
75 |
76 |
77 | var AddTodo = react.createClass({
78 | render: function() {
79 | var that = this;
80 | return hx`
81 |
84 | Add Todo
92 |
`
93 | }
94 | })
95 | AddTodo = connect(null, null)(AddTodo);
96 |
97 |
98 | var getVisibleTodos = function(todos,filter) {
99 | switch (filter) {
100 | case 'SHOW_ALL' :
101 | return todos
102 | case 'SHOW_COMPLETED' :
103 | return todos.filter(function(t) { return t.completed })
104 | case 'SHOW_ACTIVE' :
105 | return todos.filter(function(t) { return !t.completed })
106 | default:
107 | break;
108 | }
109 | }
110 | var Todo = react.createClass({
111 | render: function() {
112 | var that = this;
113 | return hx`${this.props.text} `
115 | }
116 | })
117 | var TodoList = react.createClass({
118 | render: function() {
119 | var that = this;
120 | return hx`
121 | ${this.props.todos.map(function(todo) {
122 | return react.createElement(Todo,{
123 | onClick:function() {
124 | that.props.onTodoClick(todo.id);
125 | },
126 | completed:todo.completed,
127 | text:todo.text
128 | })
129 | })}
130 | `
131 | }
132 | })
133 | var mapStateToProps = function(state) {
134 | return {
135 | todos: getVisibleTodos(state.todos,state.visibilityFilter)
136 | }
137 | }
138 | var mapDispatchToProps = function(dispatch) {
139 | return {
140 | onTodoClick: function(id) {
141 | dispatch({
142 | type:'TOGGLE_TODO',
143 | id:id
144 | })
145 | }
146 | }
147 | }
148 | var VisibleTodoList = connect(mapStateToProps,mapDispatchToProps)(TodoList)
149 |
150 |
151 |
152 |
153 | var Link = react.createClass({
154 | render: function() {
155 | var that = this;
156 | if (this.props.active) {
157 | return hx`${this.props.children} `
158 | }
159 | return hx`${this.props.children} `;
163 | }
164 | })
165 | var FilterLink = connect(function(state,ownProps) {
166 | return {
167 | active : (ownProps.filter === state.visibilityFilter),
168 | children : ownProps.children
169 | }
170 | },function(dispatch,ownProps) {
171 | return {
172 | onClick: function() {
173 | dispatch({
174 | type:'SET_VISIBILITY_FILTER',
175 | filter:ownProps.filter
176 | })
177 | }
178 | }
179 | })(Link)
180 | var Footer = react.createClass({
181 | render: function() {
182 | return hx`${react.createElement(FilterLink,{filter:'SHOW_ALL',children:'All'})}
183 | ${react.createElement(FilterLink,{filter:'SHOW_ACTIVE',children:'Active'})}
184 | ${react.createElement(FilterLink,{filter:'SHOW_COMPLETED',children:'Completed'})}
`
185 | }
186 | })
187 |
188 | var TodoApp = react.createClass({
189 | render : function() {
190 | return hx`
191 | ${react.createElement(AddTodo)}
192 | ${react.createElement(VisibleTodoList)}
193 | Show ${' '}
194 | ${react.createElement(Footer)}
195 |
`
196 | }
197 | });
198 |
199 | reactdom.render(react.createElement(TodoApp),document.querySelector('#content'))
200 |
--------------------------------------------------------------------------------
/tutorial/index-example1-react-withoutClass.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tutorial/index-example2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tutorial/index-example3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tutorial/index-example4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tutorial/index-example5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tutorial/index-example6.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------