redux: I give the initialState in createStore and then combineReducers show one of my reducers returned undefined during initialization
in reducers:
const todoBlog = combineReducers({
blogTypeVisibilityFilter,
blogs
})
in blogTypeVisibilityFilter:
const blogTypeVisibilityFilter = (state, action)=>{
switch (action.type) {
case 'BLOG_TYPE_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
export default blogTypeVisibilityFilter;
in blogs:
const blogs = (state,action)=>{
return state
}
in createStore:
const initialState = {
blogTypeVisibilityFilter:'SHOW_ALL_BLOG',
blogs:data.data,
}
const store = createStore(reducer,initialState,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
and then it shows wrong:
Reducer “blogTypeVisibilityFilter” returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don’t want to set a value for this reducer, you can use null instead of undefined.
but when i just change
const todoBlog = combineReducers({
blogTypeVisibilityFilter,
blogs
})
to
const todoBlog = (state={},action)=>{
return{
blogTypeVisibilityFilter:blogTypeVisibilityFilter(state.blogTypeVisibilityFilter,action),
blogs:blogs(state.blogs,action)
}
}
in reducers it runs well and without any errors
why i use combineReducers it goes wrong?
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 30 (13 by maintainers)
This is a bug tracker, not a support system. For usage questions, please use Stack Overflow or Reactiflux. Thanks!
@JoseFMP :
Ah, I think I know what the issue is. This is specific to how
combineReducers()
works.combineReducers
expects that all of the “slice reducers” you give it will follow a couple rules. In particular, it expects that if your reducer is called withstate === undefined
, it will return a suitable default value. To verify this,combineReducers()
will actually call your reducer with(undefined, {type : "SOME_RANDOMIZED_ACTION_TYPE"})
to see whether it returns undefined or a “real” value.Your reducers currently do nothing except return whatever’s passed in. That means that if
state
is undefined, they will return undefined. So,combineReducers()
is telling you you’re breaking the result that it expects.Just change the declarations to something like
configReducer = (config = {}, action)
, etc, and that will fix the warnings.Again, to be clear: this is not a bug. This is behavior validation.
@Jhon-Snow-008 Multiple problems:
accountReducer
default
case does not doreturn state
.Modern Redux looks like this. Please don’t follow any tutorials showing you the legacy style:
@markerikson Yes you are correct. I know already the documentation about the initial state. What I mean (and I do believe is the reason this issue was created and people also meant in this direction) is that it is counter-intuitive to provide “an initial state” when creating the store and still define an “default state” in the slice reducers (or root reducer). I.e. because very often, but not necessarily, they are the same, or very related, it feels counter-intuitive to have to define them twice. See as an exapmple the posts of @ElonXun or @Vittly who got confused same as me. I.e. my remark is not the API of Redux, is about how intuitive it feels using the API of Redux in this particular scenario, from a purely human perspective.
Notice that last paragraph is about the human feeling when using the API of redux. The machinery implementation or reasons behind it might be totally legit. But as an API consumer it feels confusing.
For instance, for me, when developing I very frequently have an initial state in my application. So Usually I need to type it twice. Once to plug it when I create the store and another time to distribute it as default value in the slice reducers. Of course many solutions for that. But the principle that for me as human makes it confusing is that I have to type twice the same thing.
However I do reckon having a special case in which the initial state is set and not making compulsory that the slice reducers or root reducer have a “default state” is more trouble some than still making it mandatory.
So the only contribution here is to mention that it feels a little bit counter-intuitive. But just that.
Thank you @markerikson . About the documentation:
So if the reducer is called with an unknown action, I should return the same state as the reducer does not know what the action should do in this reducer.
When creating the store, Redux checks the reducers by sending them an unknown action and previous state
undefined
. So if the previous state wasundefined
the reducer should returnundefined
according to the documentation (because the reducer does not know the action). But If the reducer returnsundefined
, I guarantee you no Redux app could work.For the example code:
With
combineReducers
, each slice reducer is expected to “own” its slice of state. That means providing an initial value in case the current slice is undefined, andcombineReducers
will point out if you’re not doing that.