-
-
Notifications
You must be signed in to change notification settings - Fork 15.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#1792 candidate: Make combineReducers shape-agnostic #1817
Conversation
…ns. Leave old warnings/errors in tact.
|
I'm 👎 on this. combineReducers is a convenience function, not a requirement for Redux to operate. If you want to use another library to store the results of your reducers, I would build bindings for it and implement your own version of this function. This adds too many abstractions. |
Closing due to lack of input. I'll reopen if some support for this can be drummed up (of course, I'm still against it, sorry :( ) |
@borkxs , @timdorr , @jimbolla , @gaearon : I'm seriously interested in revisiting this idea. Tim, I see you closed this a year ago as a "eh, we don't want this" decision. On the other hand, in November you said at #1768 (comment) :
Is the approach of defining I personally am in favor of adding this, and also adding options to make the key warnings and dropping of unhandled slices configurable (related to #2427 ). |
I didn't have any specific API or structure in mind, just the overall goal of a composable combineReducers. I'm happy to examine it, but we should have scalability in mind. If it can solve the issues of #1768 at the same time, that's even better. |
I had an idea some time ago how to implement some kind of 'utils' in the reducers, so they would work either with ImmutableJS or without it. const redux = require('redux')
const ini = {
count: 0,
nested: {
sample: 1
}
}
const countReducer = (state = ini, action) => {
const u = action.utils
switch(action.type) {
case 'increment':
console.log('Current state tree:', u.getState())
return u.merge(state, {
count: u.get(state, 'count') + action.payload,
nested: u.merge(u.get(state, 'nested'), {
newPropInNested: 2
})
})
default:
return u.object(state)
}
}
const addUtils = api => {
const utils = {
get: (obj, prop) => obj[prop],
object: obj => obj, // Use: obj => Immutable.Map(obj) for ImmutableJS, for instance
merge: (...objs) => Object.assign({}, ...objs),
getState: () => api.getState() // Additionally allow access to entire state
// other helpers or utils
}
return dispatch => action => {
const a = Object.assign({}, action)
a.utils = utils
dispatch(a)
}
}
const store = redux.createStore(countReducer, redux.applyMiddleware(addUtils))
store.subscribe(() => {
console.log('State tree changed:', store0.getState())
})
store.dispatch({ type: 'increment', payload: 10 }) However, it relays in the fact that I will never send a 'utils' prop in the action object to the dispatch method. My proposal would be to make the middlewareApi available as third parameter in the reducers, so it can be extended instead of changing anything in the combineReducers fn: const countReducer = (state = null, action, middlewareApi) => { // middlewareApi.utils = {...}
switch(action.type) {
default:
return state
}
}
const middleware = middlewareApi => {
middlewareApi.utils = {
get: (obj, prop) => obj[prop],
merge: (...objs) => Object.assign({}, ...objs)
}
return dispatch => action => dispatch(action)
}
const store = redux.createStore(countReducer, redux.applyMiddleware(middleware)) This way, it even exposes |
would love to see this
i've completely defined my state tree, but i have no state, this is really odd to me |
Candidate for #1792. Adds options parameter to
combineReducers
which can includeget
,create
, andkeys
methods. There is noset
method because we can just usecreate
instead.Adds a few new warnings and errors relevant to these methods without altering the old warnings and errors. The
isPlainObject
warning now just checks fortypeof state === 'object'
, so it still warns when something like aNumber
is passed in.The keys methods is for iterating over the state keys, which is needed to check for unexpected keys. It can be excluded and will simply warn if the result of the default
Object.keys(...)
doesn't match the reducer shape.Also added a param to
getUnexpectedStateShapeWarningMessage
to pass in the already computedreducerKeys
instead of recalculating them from the reducer.