diff --git a/examples/actions/CounterActions.js b/examples/actions/CounterActions.js index 737f90a95d..d379003c4e 100644 --- a/examples/actions/CounterActions.js +++ b/examples/actions/CounterActions.js @@ -7,7 +7,9 @@ export function increment() { } export function incrementIfOdd() { - return (dispatch, { counter }) => { + return (dispatch, getState) => { + const { counter } = getState(); + if (counter % 2 === 0) { return; } diff --git a/examples/components/Counter.js b/examples/components/Counter.js index 2f7eae6905..a365fcba0c 100644 --- a/examples/components/Counter.js +++ b/examples/components/Counter.js @@ -8,7 +8,7 @@ export default class Counter { }; render() { - const { increment, decrement, counter } = this.props; + const { increment, incrementIfOdd, decrement, counter } = this.props; return (
Clicked: {counter} times @@ -16,6 +16,8 @@ export default class Counter { {' '} + {' '} +
); } diff --git a/src/Redux.js b/src/Redux.js index cd05470659..067f04400b 100644 --- a/src/Redux.js +++ b/src/Redux.js @@ -1,11 +1,15 @@ import createDispatcher from './createDispatcher'; import composeStores from './utils/composeStores'; +import thunkMiddleware from './middleware/thunk'; export default class Redux { constructor(dispatcher, initialState) { if (typeof dispatcher === 'object') { // A shortcut notation to use the default dispatcher - dispatcher = createDispatcher(composeStores(dispatcher)); + dispatcher = createDispatcher( + composeStores(dispatcher), + getState => [ thunkMiddleware(getState) ] + ); } this.state = initialState; diff --git a/src/createDispatcher.js b/src/createDispatcher.js index b725dca3dd..130f2add81 100644 --- a/src/createDispatcher.js +++ b/src/createDispatcher.js @@ -1,20 +1,24 @@ -export default function createDispatcher(store) { +import compose from './utils/composeMiddleware'; + +export default function createDispatcher(store, middlewares = []) { return function dispatcher(initialState, setState) { let state = store(initialState, {}); setState(state); - function dispatchSync(action) { + function dispatch(action) { state = store(state, action); setState(state); return action; } - function dispatch(action) { - return typeof action === 'function' ? - action(dispatch, state) : - dispatchSync(action); + function getState() { + return state; + } + + if (typeof middlewares === 'function') { + middlewares = middlewares(getState); } - return dispatch; + return compose(...middlewares, dispatch); }; } diff --git a/src/index.js b/src/index.js index 79fced8d89..308223c278 100644 --- a/src/index.js +++ b/src/index.js @@ -11,5 +11,6 @@ export provide from './components/provide'; export connect from './components/connect'; // Utilities +export compose from './utils/composeMiddleware'; export composeStores from './utils/composeStores'; export bindActionCreators from './utils/bindActionCreators'; diff --git a/src/middleware/thunk.js b/src/middleware/thunk.js new file mode 100644 index 0000000000..a80a78159c --- /dev/null +++ b/src/middleware/thunk.js @@ -0,0 +1,10 @@ +export default function thunkMiddleware(getState) { + return (next) => { + const recurse = (action) => + typeof action === 'function' ? + action(recurse, getState) : + next(action); + + return recurse; + }; +} diff --git a/src/utils/composeMiddleware.js b/src/utils/composeMiddleware.js new file mode 100644 index 0000000000..fcedfc20a1 --- /dev/null +++ b/src/utils/composeMiddleware.js @@ -0,0 +1,3 @@ +export default function compose(...middlewares) { + return middlewares.reduceRight((composed, m) => m(composed)); +}