Skip to content

Commit

Permalink
Use same style for types as redux-promise-middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejbartas committed Nov 9, 2015
1 parent e0d2002 commit bc79566
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 30 deletions.
38 changes: 13 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ import { createStore, combineReducers, applyMiddleware } from 'redux';
import combineActionsMiddleware from 'redux-combine-actions';
import * as reducers from './reducers';

let createStoreWithMiddleware = applyMiddleware(combineActionsMiddleware)(createStore);
let createStoreWithMiddleware = applyMiddleware(
combineActionsMiddleware({
promiseTypeSuffixes: ['START', 'SUCCESS', 'ERROR']
})
)(createStore);

let reducer = combineReducers(reducers);
let store = createStoreWithMiddleware(reducer);
```

To use the middleware, you action creator must return action with the following fields:

- `types` - An array of action types in the next notation: [PENDING, SUCCESS, ERROR], where PENDING action is dispatched immediately, SUCCESS action is dispatched only if all child actions were executed successfully and ERROR action is dispatched only if an error occurred.
- `payload` - An array of [action creators](http://gaearon.github.io/redux/docs/basics/Actions.html#action-creators). This field must contain set of functions which shall be dispatched. For example, it can be [ordinary action creators](#simple-usage), or action creators that return a [promise](#with-promises) (see [redux-promise](https://github.com/acdlite/redux-promise) or [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware)), in this case, you can specify `sequence` option.
- `type` - An action type which will be used to create ACTION_CONSTANTS by adding `promiseTypeSuffixes`. Call will start with PENDING action which is dispatched immediately, SUCCESS action is dispatched only if all child actions were executed successfully and ERROR action is dispatched only if an error occurred.
- `payload` - An array of [action creators](http://gaearon.github.io/redux/docs/basics/Actions.html#action-creators). This field must contain set of functions which shall be dispatched. For example, it can be [ordinary action creators](#simple-usage), or action creators that return a [promise](#with-promises) (see [redux-promise](https://github.com/acdlite/redux-promise) or [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware)), in this case, you can specify `sequence` option.
- `sequence` - Specifies actions sequence. If `true` - dispatch array of action creators in sequential order, else - dispatch in parallel.

The middleware returns a promise to the caller and a [FSA](https://github.com/acdlite/flux-standard-action) compliant action for both SUCCESS and ERROR action types.
Expand All @@ -48,11 +52,7 @@ export function increment() {
export function addTodoAndIncrement({text}) {

return {
types: [
'COMBINED_ACTION_START',
'COMBINED_ACTION_SUCCESS',
'COMBINED_ACTION_ERROR'
],
type: 'COMBINED_ACTION',

// Pass actions in array
payload: [addTodo.bind(null, text), increment]
Expand All @@ -72,11 +72,7 @@ Using in combination with [redux-promise-middleware](https://github.com/pburtcha
```js
export function getProviders() {
return {
types: [
'PROVIDERS_GET_PENDING',
'PROVIDERS_GET_SUCCESS',
'PROVIDERS_GET_ERROR'
],
types: 'PROVIDERS_GET',
payload: {
promise: api.getProvidersAsync()
}
Expand All @@ -85,11 +81,7 @@ export function getProviders() {

export function getSubscribers() {
return {
types: [
'SUBSCRIBER_GET_PENDING',
'SUBSCRIBER_GET_SUCCESS',
'SUBSCRIBER_GET_ERROR'
],
type: 'SUBSCRIBER_GET',
payload: {
promise: api.getSubscribersAsync()
}
Expand All @@ -100,11 +92,7 @@ export function getSubscribers() {
export function fetchData() {

return {
types: [
'DATABASE_FETCH_PENDING',
'DATABASE_FETCH_SUCCESS',
'DATABASE_FETCH_ERROR'
],
type: 'DATABASE_FETCH',

// Set true for sequential actions
sequence: true,
Expand All @@ -117,11 +105,11 @@ export function fetchData() {

This will dispatch actions one after another:

*`DATABASE_FETCH_PENDING`* > *`PROVIDERS_GET_PENDING`* > *`PROVIDERS_GET_SUCCESS`* > *`SUBSCRIBER_GET_PENDING`* > *`SUBSCRIBER_GET_SUCCESS`* > *`DATABASE_FETCH_SUCCESS`*
*`DATABASE_FETCH_START`* > *`PROVIDERS_GET_START`* > *`PROVIDERS_GET_SUCCESS`* > *`SUBSCRIBER_GET_START`* > *`SUBSCRIBER_GET_SUCCESS`* > *`DATABASE_FETCH_SUCCESS`*

If you set `sequence` to `false` then all child actions will be dispatched in parallel:

*`DATABASE_FETCH_PENDING`* > *`PROVIDERS_GET_PENDING`* > *`SUBSCRIBER_GET_PENDING`* > *`PROVIDERS_GET_SUCCESS`* > *`SUBSCRIBER_GET_SUCCESS`* > *`DATABASE_FETCH_SUCCESS`*
*`DATABASE_FETCH_START`* > *`PROVIDERS_GET_START`* > *`SUBSCRIBER_GET_PENDING`* > *`PROVIDERS_GET_SUCCESS`* > *`SUBSCRIBER_GET_SUCCESS`* > *`DATABASE_FETCH_SUCCESS`*

## License

Expand Down
14 changes: 9 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@ function isArrayOfFunctions(array) {
return Array.isArray(array) && array.length > 0 && array.every(item => item instanceof Function);
}

const defaultTypes = ['PENDING', 'FULFILLED', 'REJECTED'];

export default function reduxCombineActions() {
const promiseTypeSuffixes = config.promiseTypeSuffixes || defaultTypes;

return next => action => {
if (!isArrayOfFunctions(action.payload)) {
return next(action);
}

const { types, sequence } = action;
const { types, sequence, meta } = action;
const actions = action.payload;
const [ PENDING, FULFILLED, REJECTED ] = types;
const [ PENDING, FULFILLED, REJECTED ] = (meta || {}).promiseTypeSuffixes || promiseTypeSuffixes;
let promise;

next({
type: PENDING
type: `${type}_${PENDING}`
});

if (sequence) {
Expand All @@ -26,12 +30,12 @@ export default function reduxCombineActions() {
return promise.then(
payload => next({
payload,
type: FULFILLED
type: `${type}_${FULFILLED}`
}),
error => next({
payload: error,
error: true,
type: REJECTED
type: `${type}_${REJECTED}`
})
);
};
Expand Down

0 comments on commit bc79566

Please sign in to comment.