With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.
In this article, we’ll look at how to define and use the mapDispatchToProps
function to map dispatch to props so we can call them in our React components.
Approaches for Dispatching
dispatch
is a function of the Redux store. We call the store.dispatch
method to dispatch an action to the tore.
It’s the only way to trigger a state change.
React components never access the store directly. We use the connect
function to do it.
React Redux gives us 2 ways to let our components dispatch actions. We can either receive dispatch
as a prop to dispatch actions itself, or we can use the connect
function with a mapDispatchToProps
function and pass as props to our component.
Default: dispatch
as a Prop
For example, if we have the following code:
import React from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";
function message(state = "", action) {
switch (action.type) {
case "SET_MESSAGE":
return action.message;
default:
return state;
}
}
const store = createStore(message);
const mapStateToProps = (state, ownProps) => {
const { color } = ownProps;
return { color, message: state };
};
function App({ dispatch, message }) {
const onClick = () => {
if (message === "bar") {
dispatch({ type: "SET_MESSAGE", message: "foo" });
} else {
dispatch({ type: "SET_MESSAGE", message: "bar" });
}
};
return (
<div className="App">
<button onClick={onClick}>Click Me</button>
<p>{message}</p>
</div>
);
}
App = connect(mapStateToProps)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
Then when we click the button, we toggle between ‘foo’ and ‘bar’ being displayed because the connect
higher-order component gives us the dispatch
prop, which we can use to dispatch actions to our store.
Providing a mapDispatchToProps
Parameter
The second way to use the mapDispatchToProps
function to map the dispatch functions to our React component as props.
This is useful because we don’t have to call dispatch
with all the arguments all the time.
It makes the dispatch implementation more declarative. With mapDispatchToProps
, our component code doesn’t need to be aware of dispatch
anymore.
mapStateToProps
encapsulates the logic of talking to the Redux store so we don’t have to worry about it.
Two Forms of mapDispatchToProps
mapStateToProps
can take the form of a function or an object. The function version allows for more customization since it as access to dispatch
and ownProps
as an option.
The object shorthand is shorter and easier to use. It’s better to use the object unless we have to customize dispatching in some way.
We’ll look at how to define mapDispatchToProps
as a function.
Photo by Stephanie Studer on Unsplash
Defining mapDispatchToProps
As A Function
We can define mapDispatchToProps
as a function by defining a function that takes dispatch
and optionally ownProps
and calling dispatch
with some action in the function.
We can use mapDispatchToProps
as follows:
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
import { connect, Provider } from "react-redux";
import { createStore } from "redux";
function messages(state = 0, action) {
const words = ["foo", "bar", "baz"];
switch (action.type) {
case "GET_BY_INDEX":
return words[action.index];
default:
return state;
}
}
const store = createStore(messages);
function Message({ getByIndex, index, message }) {
useEffect(() => {
getByIndex(index);
}, []);
return (
<div className="App">
<p>{message}</p>
</div>
);
}
const mapStateToProps = (state, ownProps) => {
return { message: state };
};
const mapDispatchToProps = (dispatch, ownProps) => {
const { index } = ownProps;
return {
getByIndex: index => dispatch({ type: "GET_BY_INDEX", index })
};
};
Message = connect(
mapStateToProps,
mapDispatchToProps
)(Message);
function App() {
return (
<div className="App">
<Message index={0} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
In the code above, we have the store
which lets us get messages from a list of words from the words
array.
Then we defined mapDispatchToProps
as follows:
const mapDispatchToProps = (dispatch, ownProps) => {
const { index } = ownProps;
return {
getByIndex: index => dispatch({ type: "GET_BY_INDEX", index })
};
};
In the code above, we have ownProps
to access the index
prop that we passed to the Message
component.
Then we returned an object with the getByIndex
method which takes an array index
then we call dispatch
with action type
'GET_BY_INDEX'
and the index
property with the index
parameter as the value.
In the Message
component, we get the getByIndex
function that we returned from mapDispatchToProps
, and index
prop, and the message
prop that we got from mapStateToProps
and we used all of them.
We called getByIndex
with the index
prop value to get the string from the store with the given index
in the useEffect
callback. Then we displayed what we retrieved by adding:
<p>{message}</p>
Note that each field that returned in the object of mapStateTiProps
will become a separate prop for our own component.
They’ll be merged with existing props.
Conclusion
To map code for dispatching actions to our React components, we can define the mapDispatchToProps
function, which takes the dispatch
function and ownProps
as arguments. dispatch
is what we call to dispatch actions to the store, and ownProps
is an object with the props that we passed into components.
For dispatching simple actions, we can just use the connect
function without defining a mapDispatchToProps
function and we can call props.dispatch
directly in the component to dispatch store actions since the connect
higher-order component passed that to our component.