Defining and Using React Redux mapDispatchToProps

John Au-Yeung - Jan 25 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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
);
Enter fullscreen mode Exit fullscreen mode

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
);
Enter fullscreen mode Exit fullscreen mode

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 })
  };
};
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .