Last active
August 15, 2016 21:28
-
-
Save butchler/28988d505af4de49ce83e6cc28bc7c36 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Wrap combineReducers to pass a namespace as the third argument | |
// to each reducer, so that each reducer can know where it is in | |
// the state and accept namespaced actions targeted for it. | |
function combineReducersWithNamespace(reducers) { | |
return (state, action, namespace) => { | |
const newState = {}; | |
Object.keys(reducers).forEach(name => { | |
const reducerNamespace = namespace ? | |
namespace + '.' + name : | |
name; | |
newState[name] = reducer(state[name], action, namespace); | |
}); | |
return newState; | |
}; | |
} | |
// Higher-order reducer to create a namespacedReducer reducer, | |
// which accepts namespaced actions with a matching namespace. | |
function namespacedReducer(reducer) { | |
return (state, action, namespace) => { | |
if (namespace !== undefined && | |
action.type === 'NAMESPACED_ACTION' && | |
action.payload.namespace === namespace) { | |
return reducer(state, action.payload.action); | |
} else { | |
return reducer(state, action); | |
} | |
}; | |
} | |
... | |
// Example | |
// ======= | |
// State: | |
const store = createStore(combineReducersWithNamespace({ | |
ui: combineReducersWithNamespace({ | |
form1: namespacedReducer(formReducer), | |
form2: namespacedReducer(formReducer), | |
}), | |
}); | |
... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Higher-order reducer to create a namespacedReducer reducer, | |
// which accepts namespaced actions with a matching namespace. | |
function namespacedReducer(namespace, reducer) { | |
return (state, action) => { | |
if (action.type === 'NAMESPACED_ACTION' && | |
action.payload.namespace === namespace) { | |
return reducer(state, action.payload.action); | |
} else { | |
return reducer(state, action); | |
} | |
}; | |
} | |
// Wraps an action in another action so that it only gets | |
// handled by the namespacedReducer with the same namespace. | |
function namespacedAction(namespace, action) { | |
return { | |
type: 'NAMESPACED_ACTION', | |
payload: { | |
namespace, | |
action, | |
}, | |
}; | |
} | |
// Example | |
// ======= | |
// State: | |
const store = createStore(combineReducers({ | |
ui: combineReducers({ | |
form1: namespacedReducer('ui.form1', formReducer), | |
form2: namespacedReducer('ui.form2', formReducer), | |
}), | |
}); | |
// Connected component for form: | |
function mapStateToProps(state, ownProps) { | |
const formState = state.ui[ownProps.formId]; | |
return { | |
state.errorMessage, | |
}; | |
} | |
function mapDispatchToProps(dispatch, ownProps) { | |
const namespace = 'ui.' + formId; | |
return { | |
onSumbit: dispatch(namespacedAction(namespace, formOnSubmitAction)); | |
}; | |
} | |
const NamespacedForm = connect(mapStateToProps, mapDispatchToProps)(Form); | |
// Usage: | |
<NamespacedForm formId="form1" ... /> | |
<NamespacedForm formId="form2" ... /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment