Redux docs for bindActionCreators states that:
The only use case for
bindActionCreators
is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it.
What would be an example where bindActionCreators
would be used/needed?
Which kind of component would not be aware of Redux?
What are the advantages/disadvantages of both options?
//actionCreator
import * as actionCreators from './actionCreators'
function mapStateToProps(state) {
return {
posts: state.posts,
comments: state.comments
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(actionCreators, dispatch)
}
vs
function mapStateToProps(state) {
return {
posts: state.posts,
comments: state.comments
}
}
function mapDispatchToProps(dispatch) {
return {
someCallback: (postId, index) => {
dispatch({
type: 'REMOVE_COMMENT',
postId,
index
})
}
}
}
More complete example, pass an object full of action creators to connect:
99% of the time, it's used with the React-Redux
connect()
function, as part of themapDispatchToProps
parameter. It can be used explicitly inside themapDispatch
function you provide, or automatically if you use the object shorthand syntax and pass an object full of action creators toconnect
.The idea is that by pre-binding the action creators, the component you pass to
connect()
technically "doesn't know" that it's connected - it just knows that it needs to runthis.props.someCallback()
. On the other hand, if you didn't bind action creators, and calledthis.props.dispatch(someActionCreator())
, now the component "knows" that it's connected because it's expectingprops.dispatch
to exist.I wrote some thoughts on this topic in my blog post Idiomatic Redux: Why use action creators?.
I'll try to answer the original questions ...
Smart & Dumb components
In your first question you basically ask why
bindActionCreators
is needed in the first place, and what kind of components should not be aware of Redux.In short the idea here is that components should be split into smart (container) and dumb (presentational) components. Dumb components work on the need-to-know basis. Their soul job is to render given data to HTML and nothing more. They shouldn't be aware of inner workings of the application. They can be seen as the skin deep front layer of your application.
On the other hand smart components are kind of a glue, which prepares data for the dumb components and preferably does no HTML rendering.
This kind of architecture promotes loose coupling between UI layer and the data layer underneath. This in turns allows easy replacement of any of the two layers with something else (i.e. a new design of the UI), which will not break the other layer.
To answer your question: dumb components shouldn't be aware of Redux (or any unnecessary implementation detail of the data-layer for that matter) because we might want to replace it with something else in the future.
You can find more about this concept in the Redux manual and in greater depth in article Presentational and Container Components by Dan Abramov.
Which example is better
The second question was about advantages/disadvantages of the given examples.
In the first example the action creators are defined in a separate
actionCreators
file/module, which means they can be reused elsewhere. It's pretty much the standard way of defining actions. I don't really see any disadvantages in this.The second example defines action creators inline, which has multiple disadvantages:
consts
separately, so that they can be referenced in reducers - that would reduce a chance for typing mistakesThe second example has one advantage over the first one - it's faster to write! So if you don't have greater plans for your code, it might be just fine.
I hope I managed to clarify things a bit ...
I don't think that the most popular answer, actually addresses the question.
All of the examples below essentially do the same thing and follow the no "pre-binding" concept.
Option
#3
is just a shorthand for option#1
, so the real question why one would use option#1
vs option#2
. I've seen both of them used in react-redux codebase, and I find it is rather confusing.I think the confusion comes from the fact that all of the examples in
react-redux
doc usesbindActionCreators
while the doc for bindActionCreators (as quoted in the question itself) says to not use it with react-redux.I guess the answer is consistency in the codebase, but I personally prefer explicitly wrapping actions in dispatch whenever needed.
The docs statement is very clear:
This is clearly a use case that may arise in the following and only one condition:
Lets say, we have component A and B:
Inject to react-redux: (A)
Injected by react-redux: (B)
Noticed of the following?
We updated the redux store through the component A whilst we were unknown of redux store in component B.
We're not updating in component A. To know what exactly I mean, you may explore this post. I hope you'll have an idea.