Should mapStateToProps be called every time an action is dispatched?
See original GitHub issueI 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
const foo = (state = true, action) =>{
switch (action.type) {
case "foo" :
return false;
default :
return state;
}
}
const bar = (state = 0, action) => {
switch (action.type) {
case "bar" :
return state + 1;
default :
return state;
}
}
const rootReducer = combineReducers({
foo,
bar
});
Container
import React, { Component } from 'react';
import { connect } from 'react-redux';
class Container extends Component {
constructor(props) {
super(props);
this.onBarClick = this.onBarClick.bind(this);
}
onBarClick () {
this.props.dispatch({
type : "bar"
});
// I expect mapStateToProps to be called here
// which would allow me to check the value
// of the updated props, and dispatch foo if the
// condition is met
if (this.props.isBarGreaterThanEqual3) {
this.props.dispatch({
type : "foo"
});
}
}
render () {
return (
<div>
<button onClick={this.onBarClick}>Click bar</button>
</div>
)
}
}
const mapStateToProps = (state) => {
console.log("map state to props");
return Object.assign({}, state, {
isBarGreaterThanEqual3 : state.bar >= 3
});
};
export default connect(mapStateToProps)(Container);
If it is wrong of me to expect mapStateToProps
to be called after every dispatch
, 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?
Issue Analytics
- State:
- Created 8 years ago
- Reactions:2
- Comments:8 (4 by maintainers)
Top Results From Across the Web
Connect: Extracting Data with mapStateToProps - React Redux
It is called every time the store state changes. It receives the entire store state, and should return an object of data this...
Read more >redux connect mapStateToProps not called when action is ...
When I put the store on window ( window.store=store ), add a console.log in the mapStateToProps, then in the console I dispatch an...
Read more >React Redux
React Redux #291: Should mapStateToProps be called every time an action is dispatched? Stack Overflow: Cleaner/shorter way to update nested state in Redux?...
Read more >MapStateToProps and MapDispatchToProps in React Redux
It also implements shouldComponentUpdate comparisons inside. Which means yes it fires every time when state changes but our component props will be changed...
Read more >Connect | React Redux
If your mapStateToProps function is declared as taking one parameter, it will be called whenever the store state changes, and given the store...
Read more >Top Related Medium Post
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
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.props.isBarGreaterThanEqual3
to update instantaneously after youdispatch
in the same event handler.This is not how React works. In React, state changes (and Reacf Redux uses
setState
internally) are potentially asynchronous. This is because React batches update that happen during the same event handler. So callingdispatch
will update the store state immediately but your components will be updated a bit later during the same tick, together.Instead of assuming
dispatch
updates props synchronously, you can usecomponentWillReceiveProps
to react to changes in the props when they happen.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.
It is fair to say
mapStateToProps
is called after but not necessarily immediately after the dispatch. It is called when the component is about to re-render, which depends on whether React batches the updates or not. By default, React batches updates from event handlers.Since one depends on the state of the other, maybe they should just be a single reducer.
Another, simpler, option is to keep them separate, and compute the result as derived data:
In this case, we defined a selector called
isFooishEnough
. You can call it from yourmapStateToProps
and use that value instead. In general, this is the preferred pattern: whatever can be computed from Redux store state, should not be there.