Reputation: 151
I've identified 2 patterns for getting state in an action creator and am wondering which is better:
Example of each:
class SomeComponent {
render() {
return (
<Button onPress={this.props.networkCall}/>
)
}
}
const mapDispatchToProps = {
networkCall: actions.networkCall,
}
export default connect(undefined, mapDispatchToProps)(SomeComponent)
export networkCall() {
return (dispatch, getState) => {
const { dataForNetworkCall } = getState().someReducer
dispatch(pending())
axios.get(`something/${dataForNetworkCall}/something2`)
.then(() => {
dispatch(success())
}
...
}
}
OR
class SomeComponent {
render() {
const { networkCall, dataForNetworkCall } = this.props
return (
<Button onPress={networkCall(dataForNetworkCall)}/>
)
}
}
function mapStateToProps(state) {
const { dataForNetworkCall } = state.someReducer
return { dataForNetworkCall }
}
const mapDispatchToProps = {
networkCall: actions.networkCall,
}
export default connect(mapStateToProps, mapDispatchToProps)(SomeComponent)
export networkCall(dataForNetworkCall) {
return (dispatch) => {
dispatch(pending())
axios.get(`something/${dataForNetworkCall}/something2`)
.then(() => {
dispatch(success())
}
...
}
}
I feel like 2 is a bad idea because it involves passing state to the Component just to pass it back to Redux. However, there seems to be a lot of articles online saying option 1 is an anti-pattern (including Dan Abramov himself saying it is an anti-pattern). So, what is the "best" way?
Upvotes: 3
Views: 510
Reputation: 36209
I always follow the latter example, meaning that my action creators are not dependent on a store
. However, there was a case when I had to pass user token to almost every action that required interaction with server API. Instead of repeatedly pass it to every action creator or accessing it within with getState()
I wrote a custom middleware (not that difficult) that would recognize these actions and enrich them with another prop called userToken
.
Back to the Dan Abramov answer. He says in a comment:
It’s fine to read from the store in the action creator.
which is confusing to me, but I think what he meant is that is fine to do it for certain reasons:
I think it’s acceptable is for checking cached data before you make a request, or for checking whether you are authenticated (in other words, doing a conditional dispatch)
... and that using getState
may result in a situation where:
... it is hard to trace where those incorrect values come from because they are already part of the action, rather than directly computed by a reducer in response to an action.
What I think he means is that action creators should not pass updated parts of the store that get replaced by the reducer, but action should describe what is happening and the reducers should handle the update:
Not:
here is the new
item
list - replace it in the store
But:
we need to remove the
item
with id:5
- handle it
...which is a bit different scenario than accessing a value from store to use it in a request. I advice you to read the linked blog. It answers in deep your question and there are some arguments with examples about whats best. TL;DR - it's a debate which approach is better.
Upvotes: 2