Skip to content

Instantly share code, notes, and snippets.

@jamesplease
Last active August 26, 2019 02:19
Show Gist options
  • Save jamesplease/09e1e1f3f08113acec60e093dd5e42f3 to your computer and use it in GitHub Desktop.
Save jamesplease/09e1e1f3f08113acec60e093dd5e42f3 to your computer and use it in GitHub Desktop.
export default function composeReducers(reducers) {
return (state, action) => {
let reducerCount = reducers.length;
let sideEffects = [];
let noUpdateCount = 0;
const reducedResult = reducers.reduceRight((prevState, reducer, index) => {
// This is to handle the asymmetry in the useReducerWithSideFffect API.
// Whereas regular reducers have a symmetric API that is state in, state out
// useReducerWithSideEffects has state in, state+sideEffects out
let state;
if (index === reducerCount - 1) {
state = prevState;
} else {
state = prevState.newState;
}
const result = reducer(state, action);
const isNoUpdate = typeof result === 'symbol';
let returnValue;
if (isNoUpdate) {
noUpdateCount++;
// If this is the last reducer and we have no update, then we must
// return the return value of the reducer, which is a Symbol.
// That way, we can return it from the entire composed reducer.
if (index === 0 && noUpdateCount === reducerCount) {
returnValue = result;
}
// Otherwise, we must NOT return the Symbol, or else this loop will crash.
else {
returnValue = {
newState: state,
};
}
}
// If the return value is not a symbol, then we always just return whatever
// the reducer gave us.
else {
returnValue = result;
}
if (result && Array.isArray(result.newSideEffect)) {
sideEffects = sideEffects.concat(result.newSideEffect);
}
return returnValue;
}, state);
const noUpdateOccurred = noUpdateCount === reducerCount;
if (noUpdateOccurred) {
return reducedResult;
}
return {
newState: reducedResult && reducedResult.newState,
newSideEffect: sideEffects,
};
};
}
@conorhastings
Copy link

if i have n reducers and the final one returns no update would my expecation be to get the updates from the first say 8/9 reducers? I would think so?

@jamesplease
Copy link
Author

jamesplease commented Aug 26, 2019

Yup! It behaves just like Redux’s composeReducers in that (and every other) regard.

@conorhastings
Copy link

ah .yeah, its been so loong since ive reeduxed makes sense, the gist looks good? would definitely ttake pr

@jamesplease
Copy link
Author

Nice. I’ll whip somethin’ up

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