I watched the egghead.io tutorial on Redux and feel like I have some sense of what Redux is trying to do, but the way it actually works is still mysterious to me. I implemented Dan's simple counter app using the react-redux connect method, but I don't really understand my implementation. There are two possible ways I tried:
Without passing dispatch:
const mapDispatchToProps = {
upIt: () => {
return ({type:'INCREMENT'}
)
},
downIt: () => {
return({type:'DECREMENT'})
}
}
Passing dispatch:
const mapDispatchToProps = dispatch => ({
upIt: () => {
dispatch({type:'INCREMENT'}
)
},
downIt: () => {
dispatch({type:'DECREMENT'})
}
})
The counter works using either or those two options, but I am not sure how the first option (where I never call 'dispatch') manages to hook up to the store.dispatch method. Is there any reason I should prefer one way of writing the method over the other?
Think of mapDispatchToProps
as an interface that passes relevant action creators to your component (these action creators appear on, and are accessed within your component as props).
Action creators are NOT the same as actions.
In Redux, an action is simply a plain JavaScript object such as the following (it can have whatever properties you want but must include the type
property):
{ type: 'INCREMENT' }
These actions are sent to the reducer, which handles how to update the state based on the actions properties.
An action creator is a function that sends these actions to the reducer when called.
So, in your examples, upIt
and downIt
are action creators, while {type:'INCREMENT'}
and {type:'DECREMENT'}
are actions.
Take upIt
for example:
upIt: () => {
return ( {type:'INCREMENT'} )
}
The connect()
function from react-redux
will intercept the action returned from this action creator function, and dispatch it to the redux store (it will then be handled by the reducer).
connect
function implementation:
connect(mapStateToProps, mapDispatchToProps)(ComponentName)
However, consider the case where you might want to dispatch multiple actions from a single action creator. How would this be possible, when a function can only return
a value once?
This is where the dispatch
parameter of mapDispatchToProps
comes in! It allows you to dispatch multiple actions from a single action creator.
For example, say you want to create a button in the UI to increment the counter, then 5 seconds later, decrement it again. Your action creator defined in mapDispatchToProps
might look something like this:
const mapDispatchToProps = dispatch => ({
incrementForFiveSeconds: () => {
dispatch( {type:'INCREMENT'} );
setTimeout(() => {
dispatch( {type:'DECREMENT'} );
}, 5000);
},
// other action creators
})
Notice how we can call the dispatch
function twice within the same action creator!
To summarize:
return
or the dispatch()
interface.dispatch()
interface.From the Redux documentation docs:
[
mapDispatchToProps(dispatch, [ownProps]): dispatchProps
] (Object or Function):If an object is passed, each function inside it is assumed to be a Redux action creator. An object with the same function names, but with every action creator wrapped into a
dispatch
call so they may be invoked directly, will be merged into the component’s props. If a function is passed, it will be givendispatch
. If you don't want to subscribe to store updates, passnull
orundefined
in place ofmapStateToProps
. It’s up to you to return an object that somehow usesdispatch
to bind action creators in your own way. (Tip: you may use thebindActionCreators()
helper from Redux.) If you omit it, the default implementation just injectsdispatch
into your component’s props. IfownProps
is specified as a second argument, its value will be the props passed to your component, andmapDispatchToProps
will be re-invoked whenever the component receives new props.
In the first case
const mapDispatchToProps = {
upIt: () => {
return ({type:'INCREMENT'}
)
},
downIt: () => {
return({type:'DECREMENT'})
}
}
mapDispatchToProps is a object and thus upIt
and downIt
are assumed to be action creators.
In the second case:
const mapDispatchToProps = dispatch => ({
upIt: () => {
dispatch({type:'INCREMENT'}
)
},
downIt: () => {
dispatch({type:'DECREMENT'})
}
})
mapDispatchToProps
is a function and thus each function inside it must be passed to dispatch
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With