From f3f095b547ee63474b9361128bb95d370da04b35 Mon Sep 17 00:00:00 2001 From: Ron Waldon Date: Tue, 23 Feb 2016 14:44:09 +1100 Subject: [PATCH] add redux-saga --- config/_base.js | 1 + package.json | 4 +++- src/layouts/CoreLayout/CoreLayout.js | 1 + src/main.js | 2 ++ src/redux/configureStore.js | 7 ++++++- src/redux/modules/counter.js | 6 +++++- src/redux/sagas/index.js | 21 +++++++++++++++++++++ src/views/HomeView/HomeView.js | 22 +++++++++++++--------- tests/test-bundler.js | 1 + 9 files changed, 53 insertions(+), 12 deletions(-) create mode 100644 src/redux/sagas/index.js diff --git a/config/_base.js b/config/_base.js index a4b166303e..43c92e8061 100644 --- a/config/_base.js +++ b/config/_base.js @@ -37,6 +37,7 @@ const config = { colors : true }, compiler_vendor : [ + 'babel-polyfill', 'classnames', 'history', 'immutable', diff --git a/package.json b/package.json index 625655d2ee..534f624282 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,9 @@ "author": "David Zukowski (http://zuko.me)", "license": "MIT", "dependencies": { + "babel-polyfill": "6.5.0", "better-npm-run": "0.0.7", - "classnames": "^2.2.3", + "classnames": "2.2.3", "co-request": "^1.0.0", "debug": "^2.2.0", "history": "^2.0.0", @@ -83,6 +84,7 @@ "react-router-redux": "^4.0.0-beta", "redux": "^3.0.0", "redux-immutable": "3.0.5", + "redux-saga": "0.9.1", "redux-thunk": "^1.0.0", "url": "^0.11.0", "yargs": "^4.1.0" diff --git a/src/layouts/CoreLayout/CoreLayout.js b/src/layouts/CoreLayout/CoreLayout.js index e6a6a38199..e5249d7054 100644 --- a/src/layouts/CoreLayout/CoreLayout.js +++ b/src/layouts/CoreLayout/CoreLayout.js @@ -1,5 +1,6 @@ import React, { PropTypes } from 'react'; import 'normalize.css'; + import '../../styles/core.css'; // Note: Stateless/function components *will not* hot reload! diff --git a/src/main.js b/src/main.js index fc4988dfa0..a6c1bf1975 100644 --- a/src/main.js +++ b/src/main.js @@ -1,8 +1,10 @@ +import 'babel-polyfill'; import React from 'react'; import ReactDOM from 'react-dom'; import createBrowserHistory from 'history/lib/createBrowserHistory'; import { useRouterHistory } from 'react-router'; import { syncHistoryWithStore } from 'react-router-redux'; + import makeRoutes from './routes'; import Root from './containers/Root'; import configureStore from './redux/configureStore'; diff --git a/src/redux/configureStore.js b/src/redux/configureStore.js index 86ed6ac757..1adb2b4b01 100644 --- a/src/redux/configureStore.js +++ b/src/redux/configureStore.js @@ -1,12 +1,17 @@ import { Map } from 'immutable'; import { applyMiddleware, compose, createStore } from 'redux'; import thunk from 'redux-thunk'; +import createSagaMiddleware from 'redux-saga'; import rootReducer from './rootReducer'; +import { rootSaga } from './sagas'; export default function configureStore (initialState = new Map()) { // Compose final middleware and use devtools in debug environment - let middleware = applyMiddleware(thunk); + let middleware = applyMiddleware( + createSagaMiddleware(rootSaga), + thunk + ); if (__DEBUG__) { const devTools = window.devToolsExtension ? window.devToolsExtension() diff --git a/src/redux/modules/counter.js b/src/redux/modules/counter.js index 4c7f2fc124..30d679ce5c 100644 --- a/src/redux/modules/counter.js +++ b/src/redux/modules/counter.js @@ -2,6 +2,7 @@ // Constants // ------------------------------------ export const COUNTER_INCREMENT = 'COUNTER_INCREMENT'; +export const COUNTER_TRIPLE = 'COUNTER_TRIPLE'; // ------------------------------------ // Actions @@ -28,9 +29,12 @@ export const doubleAsync = () => { }; }; +export const tripleSaga = () => ({ type: COUNTER_TRIPLE }); + export const actions = { increment, - doubleAsync + doubleAsync, + tripleSaga }; // ------------------------------------ diff --git a/src/redux/sagas/index.js b/src/redux/sagas/index.js new file mode 100644 index 0000000000..30c84f6fc2 --- /dev/null +++ b/src/redux/sagas/index.js @@ -0,0 +1,21 @@ +import { takeEvery } from 'redux-saga'; +import { fork, put, select } from 'redux-saga/effects'; + +import { COUNTER_TRIPLE, increment } from '../modules/counter'; + +function * counterTriple () { + let counter = yield select((state) => state.get('counter')); + yield put(increment(counter * 2)); +} + +function * watchCounterTriple () { + while (true) { + yield * takeEvery(COUNTER_TRIPLE, counterTriple); + } +} + +export function * rootSaga () { + yield [ + fork(watchCounterTriple) + ]; +} diff --git a/src/views/HomeView/HomeView.js b/src/views/HomeView/HomeView.js index 82ec7d63da..1bba57ea2d 100644 --- a/src/views/HomeView/HomeView.js +++ b/src/views/HomeView/HomeView.js @@ -2,7 +2,7 @@ import React, { PropTypes } from 'react'; import { connect } from 'react-redux'; import classnames from 'classnames'; -import { increment, doubleAsync } from '../../redux/modules/counter'; +import { increment, doubleAsync, tripleSaga } from '../../redux/modules/counter'; import DuckImage from './Duck.jpg'; import classes from './HomeView.css'; @@ -10,12 +10,6 @@ import classes from './HomeView.css'; // that we can export the undecorated component for testing. // See: http://rackt.github.io/redux/docs/recipes/WritingTests.html export class HomeView extends React.Component { - static propTypes = { - counter: PropTypes.number.isRequired, - doubleAsync: PropTypes.func.isRequired, - increment: PropTypes.func.isRequired - }; - render () { return (
@@ -35,19 +29,29 @@ export class HomeView extends React.Component { - {' '} +
); } } +HomeView.propTypes = { + counter: PropTypes.number.isRequired, + doubleAsync: PropTypes.func.isRequired, + increment: PropTypes.func.isRequired, + tripleSaga: PropTypes.func.isRequired +}; + const mapStateToProps = (state) => ({ counter: state.get('counter') }); export default connect((mapStateToProps), { increment: () => increment(1), - doubleAsync + doubleAsync, + tripleSaga })(HomeView); diff --git a/tests/test-bundler.js b/tests/test-bundler.js index cdf9353848..25427b878d 100644 --- a/tests/test-bundler.js +++ b/tests/test-bundler.js @@ -1,6 +1,7 @@ // --------------------------------------- // Test Environment Setup // --------------------------------------- +import 'babel-polyfill'; import sinon from 'sinon'; import chai from 'chai'; import sinonChai from 'sinon-chai';