I was reading the documentation for the Redux library and it has this example,
In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps()
that receives the dispatch() method and returns callback props that you want to inject into the presentational component.
This actually makes no sense. Why do you need mapDispatchToProps
when you already have mapStateToProps
?
They also provide this handy code sample:
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
Can someone please explain in laymen\'s terms what this function is and why it is useful?
I feel like none of the answers have crystallized why mapDispatchToProps
is useful.
This can really only be answered in the context of the container-component
pattern, which I found best understood by first reading:
https://medium.com/@learnreact/container-components-c0e67432e005#.1a9j3w1jl
then
http://redux.js.org/docs/basics/UsageWithReact.html
In a nutshell, your components
are supposed to be concerned only with displaying stuff. The only place they are supposed to get information from is their props.
Separated from \"displaying stuff\" (components) is:
- how you get the stuff to display,
- and how you handle events.
That is what containers
are for.
Therefore, a \"well designed\" component
in the pattern look like this:
class FancyAlerter extends Component {
sendAlert = () => {
this.props.sendTheAlert()
}
render() {
<div>
<h1>Today\'s Fancy Alert is {this.props.fancyInfo}</h1>
<Button onClick={sendAlert}/>
</div>
}
}
See how this component gets the info it displays from props (which came from the redux store via mapStateToProps
) and it also gets its action function from its props: sendTheAlert()
.
That\'s where mapDispatchToProps
comes in: in the corresponding container
// FancyButtonContainer.js
function mapDispatchToProps(dispatch) {
return({
sendTheAlert: () => {dispatch(ALERT_ACTION)}
})
}
function mapStateToProps(state} {
return({fancyInfo: \"Fancy this:\" + state.currentFunnyString})
}
export const FancyButtonContainer = connect(
mapStateToProps, mapDispatchToProps)(
FancyAlerter
)
I wonder if you can see, now that it\'s the container
[1] that knows about redux and dispatch and store and state and ... stuff.
The component
in the pattern, FancyAlerter
, which does the rendering doesn\'t need to know about any of that stuff: it gets its method to call at onClick
of the button, via its props.
And ... mapDispatchToProps
was the useful means that redux provides to let the container easily pass that function into the wrapped component on its props.
All this looks very like the todo example in docs, and another answer here, but I have tried to cast it in the light of the pattern to emphasize why.
(Note: you can\'t use mapStateToProps
for the same purpose as mapDispatchToProps
for the basic reason that you don\'t have access to dispatch
inside mapStateToProp
. So you couldn\'t use mapStateToProps
to give the wrapped component a method that uses dispatch
.
I don\'t know why they chose to break it into two mapping functions - it might have been tidier to have mapToProps(state, dispatch, props)
IE one function to do both!
[1] Note that I deliberately explicitly named the container FancyButtonContainer
, to highlight that it is a \"thing\" - the identity (and hence existence!) of the container as \"a thing\" is sometimes lost in the shorthand
export default connect(...)
syntax that is shown in most examples
It\'s basically a shorthand. So instead of having to write:
this.props.dispatch(toggleTodo(id));
You would use mapDispatchToProps as shown in your example code, and then elsewhere write:
this.props.onTodoClick(id);
or more likely in this case, you\'d have that as the event handler:
<MyComponent onClick={this.props.onTodoClick} />
There\'s a helpful video by Dan Abramov on this here: https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist
mapStateToProps()
is a utility which helps your component get updated state(which is updated by some other components),
mapDispatchToProps()
is a utility which will help your component to fire an action event (dispatching action which may cause change of application state)
mapStateToProps
, mapDispatchToProps
and connect
from react-redux
library provides a convenient way to access your state
and dispatch
function of your store. So basically connect is a higher order component, you can also thing as a wrapper if this make sense for you. So every time your state
is changed mapStateToProps
will be called with your new state
and subsequently as you props
update component will run render function to render your component in browser. mapDispatchToProps
also stores key-values on the props
of your component, usually they take a form of a function. In such way you can trigger state
change from your component onClick
, onChange
events.
From docs:
const TodoListComponent = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
const TodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
Also make sure that you are familiar with React stateless functions and Higher-Order Components
mapStateToProps
receives the state
and props
and allows you to extract props from the state to pass to the component.
mapDispatchToProps
receives dispatch
and props
and is meant for you to bind action creators to dispatch so when you execute the resulting function the action gets dispatched.
I find this only saves you from having to do dispatch(actionCreator())
within your component thus making it a bit easier to read.
https://github.com/reactjs/react-redux/blob/master/docs/api.md#arguments