Skip to content

Instantly share code, notes, and snippets.

@Aldredcz
Last active June 9, 2020 10:06
Show Gist options
  • Save Aldredcz/e89874d468655f21be2a to your computer and use it in GitHub Desktop.
Save Aldredcz/e89874d468655f21be2a to your computer and use it in GitHub Desktop.
Redux - enhance store to process multiple batched actions

Usable mainly when reducer is more like assembler for your data store changes, and main logic is put into action. So you often need to dispatch multiple smaller action, but to keep it atomic, they have to be processed in a single reduce step. This is the solution. The bonus is, it works well with devTools also.

Sourcecode:

multipleActionEnhancer.js:

export function multipleActionsEnhanceReducer(reducer) {
	return (state, action, ...rest) => {
		if (action.actions && action.actions.type && action.actions instanceof Array) {
			state = action.actions.reduce(reducer, state);
		} else {
			state = reducer(state, action);
		}

		return state;
	};
}

export function multipleActionsEnhanceDispatch(dispatch) {
	return (action) => {
		var multipleAction;

		if (action instanceof Array) {
			if (action.type === undefined) {
				action.type = action.map((a) => a.type).join(' => ');
			}

			multipleAction = {
				type: action.type,
				actions: action
			};
		}

		return dispatch(multipleAction || action);
	};
}

export function multipleActionsEnhancer() {
	return (next) => (reducer, initialState) => {
		var store = next(multipleActionsEnhanceReducer(reducer), initialState);
		store.dispatch = multipleActionsEnhanceDispatch(store.dispatch);
		return store;
	};
}

Top-level Component setup:

const createStoreFinal = compose(
	multipleActionsEnhancer(), // allows store to process array of actions synchronously
	devTools()
)(createStore);

const store = createStoreFinal(statisticsReducer);

if (module.hot) {
	// Enable Webpack hot module replacement for reducers
	module.hot.accept('stores/reducers/statistics', () => {
		const nextRootReducer = require('stores/reducers/statistics');
		store.replaceReducer(multipleActionsEnhanceReducer(nextRootReducer)); // HERE
	});
}

Example:

Then we can dispatch actions like:

return function multipleBatchedActions() {
	return [
		{
			type: ACTION1,
			payload: {
				...
			}
		}, {
			type: ACTION2,
			payload: {
				...
			}
		}
	]
}

And all these actions are processed synchronously and as single atomic operation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment