-
-
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
Warn if the initial state shape doesn't match the reducer names #302
Warn if the initial state shape doesn't match the reducer names #302
Conversation
Let's do this in |
I think it's enough to put it here before |
I think we should change |
I think that it needs an extra check because |
We don't need to worry about this if the check is moved to |
@gaearon Yeah you are right, it needs to call verifyState after mapValues are done, otherwise it'll warn everytime. I did't get mapValues right at first look. |
Hmm. The initial state can still be wrong. I guess we should just check |
@gaearon I agree. Initial state should be checked to be a plain object. |
PS: this is a duplicate of #276 . We can close mine, but maybe you can keep the failing test? |
@gaearon Yes, no problem. I've moved the check to combineReducers. |
'match shape of state object returned by reducer'; | ||
} | ||
|
||
return ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better return null
IMO.
warning( | ||
verifyStateShape(state, finalState), | ||
'Shape of initial state object given to createStore does not ' + | ||
'match shape of state object returned by reducer' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By this point the user does not really define a reducer. All they do is pass reducers
object (which they might get from import * as something
ES6 import). Therefore they won't understand which reducer the warning message is referring to.
The warning should instead say something like Unexpected key "<key>" in the initialState will be ignored. Expected to find one of the known reducer keys instead: "oneReducer", "otherReducer", ...
.
Updated with better warning message |
Looks really good. I'll test this in a day or two and get this into 1.0 release. 👍 |
Please rebase on |
@ellbee I think it's ok like this, just it's not really the complete flow. Usually you do |
@emmenko Do you mean the tests? I don't think it's a problem because this is behavior completely specific to |
Ok, thanks @gaearon! Rebased and squashed. |
👍 |
import mapValues from '../utils/mapValues'; | ||
import pick from '../utils/pick'; | ||
import invariant from 'invariant'; | ||
import { ActionTypes } from '../createStore'; | ||
import warning from 'warning'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: let's move invariant
here so their imports are together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move invariant next to warning in the import order? Can do, I just put them into alphabetical order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done
I played with this a little bit more, and I think we could still improve this a little bit:
|
Good points!
|
Sorry, my finger slipped... I wanted to ask if it would be a problem with hot reloading?
|
I don't think this would be a problem? On hot reloading the function will be re-generated so the code will run again. |
Ok, just wanted to make sure :) |
Updated pull request to add extra warnings and only call verifyStateShape once as suggested. Ideas for improvements to the warning messages are welcome! I have been wondering though if these new warnings should be invariants instead? |
@gaearon I'll have some spare time later today, is there anything else you would like me to do with this PR? |
I don't have time to look at it right now, but please do what I'd do:
|
@gaearon OK, will do. Thanks! |
Hey, awesome job. Thanks. |
Hi! I just get this warning and I don't understand what's the problem with this one.. I mean, I have an initial state from the server that looks like this for example: {
foo: [/* ... */], // ok, I've a reducer called 'foo'
bar: true, // no reducer
baz: false, // same here
} Should I have one reducer for every single state property in order to access it from my components? |
Yes, if you use combineReducers, because that's exactly what it does. It lets you assign a single reducer to each state property. You can also write the root reducer by hand, without combineReducers. Then it's up to you how to structure it. https://github.com/rackt/redux/blob/master/docs/api/combineReducers.md https://github.com/rackt/redux/blob/master/docs/basics/Reducers.md |
Thanks for the quick response! Ok, point taken... Maybe I need to think a bit more about my app state in order to know if I need the 1:1 relation between state properties and reducers... Another option could be to have 1 reducer to manage the entire state right? |
Yes. In fact that's what combineReducers generates — a single reducer. (And instead of using combineReducers you can write it by hand.) |
Ok, I'll evaluate if I need to write my own or simply use one "master" reducer (I'm doing a small app btw eheh). Many thanks for the support! :) |
Ok, not super happy with this but it is a start.
Happy to take some direction on this.