-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Should mapStateToProps be called every time an action is dispatched? #291
Comments
It should be called. Please provide a runnable project reproducing this (on Github or something like http://jsbin.com). I’m confident we don’t have bugs related to this because the library is covered by tests and used in a ton of projects. So something is off with the way you set it up but it’s hard for me to say without running the code and reproducing the issue. |
I've put an example up at https://github.com/dara76/react-redux-issue.git The app can be run with (I've changed the foo reducer to now to have initial
In the app, I expect the "Waiting for foo" message to change after 3 clicks. |
I think I (probably) see your point now. I haven’t run the app yet but from the source it looks like you expect This is not how React works. In React, state changes (and Reacf Redux uses Instead of assuming onBarClick() {
this.props.dispatch({
type : "bar"
});
}
componentWillReceiveProps(nextProps) {
if (
!this.props.isBarGreaterThanEqual3 &&
nextProps.isBarGreaterThanEqual3
) {
this.props.dispatch({
type : "foo"
});
}
} Note that also, in general, dispatching actions in response to store-dependant prop changes is an anti-pattern. If you want to react to an action, it is best to do so in reducer. If you want to calculate some state that depends on the store state, it is best to do this in a selector. |
Thanks for looking at this. Yeah, I was expecting the following flow
but you explain that
which means the flow is actually more like
So is it fair to say that I like the simplicity of this advice
Having said that, it's not clear to me how I would update
|
It is fair to say
Since one depends on the state of the other, maybe they should just be a single reducer. const reducer = (state = { counter: 0, foo: false }, action) {
switch (action.type) {
case "bar":
return Object.assign({}, state, {
counter: state.counter + 1,
foo: state.counter === 2
// depending on your use case, it could also be:
// foo: !state.foo && state.counter === 2
// foo: !state.hasEverBeenFooBefore && state.counter === 2
// etc
});
case "foo" :
return Object.assign({}, state, {
foo: true
});
default:
return state
}
} Another, simpler, option is to keep them separate, and compute the result as derived data: const bar = (state = 0, action) => {
switch (action.type) {
case "bar" :
return state + 1;
default :
return state;
}
};
const foo = (state = false, action) => {
switch (action.type) {
case "foo" :
return true;
default :
return state;
}
};
const reducer = combineReducers({
foo,
bar
});
const isFooishEnough = (state) => {
return state.foo || state.bar >= 3;
} In this case, we defined a selector called |
Thanks for the explanations and insights, they're very helpful. |
very similar doubt, i guess which got clear now reading comments. Please someone correct me if i am wrong. So basically if not using redux, and using some event handler function i call more than one setState (class or function with hook component), then react collects all the batch of changes at the very end of the event handler and then re-renders the component. |
@harry-dev98 Two things:
|
I was under the impression that
mapStateToProps
is called every time an action is dispatched which causes the store to change.In my simplified example below, this doesn't seem to be the case.
reducers.js
Container
If it is wrong of me to expect
mapStateToProps
to be called after everydispatch
, what is the recommended way to conditionally dispatch an action when the condition depends on the state of the store that has just been updated by another action?The text was updated successfully, but these errors were encountered: