How Redux's mapDispatchToProps Works
Tags: mapdispatchtoprops, redux, react
Published: 2020-10-31 10:29:49

# Overview

_**`mapDispatchToProps` gives your props indirect access to Redux's `dispatch` function. `dispatch` passes an action (a JavaScript object) to your reducer so your application’s state can update.**_

The props that get access to `dispatch` belong to the file that is written in the Redux `connect` function's second set of parentheses. For example, in `App.js`, if you write the line

```export default connect(null, mapDispatchToProps)(App);```

only the props for `App.js` will receive indirect access to the dispatch function. 

# How to Use `mapDispatchToProps`

_(The following assumes you are building a React app with a Redux store already configured)._

Let's say we are making a React app that will allow us to write reviews for something. To add a new review object to our Redux store, we will do the following in the class component `ReviewsContainer.js`:

* Make sure `react-redux` is listed in your `package.json` file. Also, in the terminal inside your project's directory, make sure you have run `npm install`.

* At the top of the file, add the line `import { connect } from 'react-redux';`. This will grant your file access to Redux's `connect` function.

* At the bottom of the file, add the line `export default connect(null, mapDispatchToProps)(ReviewsContainer);`. This lets our file use `mapDispatchToProps`. The `null` can be replaced with `mapStateToProps`. The `ReviewsContainer` part is the name of the file we're working in.

* Write your `mapDispatchToProps` function. This function goes outside of the class. **The function returns an object with keys that we'll use later via props.** If our goal is to add a review to our Redux store, we could write:

```javascript
const mapDispatchToProps = dispatch => ({
  addReview: reviewObject => 
(dispatch({ type: "ADD_REVIEW", payload: reviewObject }))
})
```

The syntax is convoluted but can be understood like this: 

The function takes in an argument of `dispatch` and returns an object with a key of `addReview`. (`dispatch` is provided by Redux's `connect` function). 

The `addReview` key points to a value which is an anonymous function. The anonymous function returns an expression that uses the `dispatch` function to send an action to the reducer. The action is this part: `{ type: "ADD_REVIEW", payload: reviewObject }`. Your reducer will expect an `action.type` of `'ADD_REVIEWS'` and an `action.payload` of `reviewObject`. The word "payload" just means the data, the meat and potatoes, that is given to the reducer.

* **To actually add a review, we could call `this.props.addReview(reviewObject)` somewhere in our `ReviewsContainer` class. This will invoke the following anonymous function:**
```reviewObject => (
    dispatch({ type: "ADD_REVIEW", payload: reviewObject })
)```
**(This function is the value of the `addReview` key of our `mapDispatchToProps` function).**

**We can give that function a review object, which can be retrieved by using action.payload in the reducer.**

* _(optional)_ If you want to add another key-value pair in your `mapDispatchToProps` function, you could write the following, which will create a deleteReview action you can send to your reducer:

```javascript
const mapDispatchToProps = dispatch => ({
  addReview: reviewObject => (
    dispatch({ type: "ADD_REVIEW", payload: reviewObject })
  ),

  deleteReview: id => (
    dispatch({ type: "DELETE_REVIEW", payload: id })
  )

})
```

# Conclusion

`mapDispatchToProps` is a function that one writes to dispatch actions to the reducer. `mapDispatchToProps` itself returns an object with any number of key-value pairs. Each key points to an anonymous function declaration that will dispatch an action object to the reducer. To invoke the anonymous function, you can call `this.props.<keyOfAnonymousFunction>()` somewhere in your class.  

In the end, `ReviewsContainer.js` looks like this:

```jsx
import React, { Component } from 'react';
import { connect } from 'react-redux';

class ReviewsContainer extends Component {

  render() {

    let reviewObject = {content: "good"}

    return (
      <div>
        
        {this.props.addReview(reviewObject)}
        {this.props.deleteReview({id: 5})}
      </div>
    )
  }
}

const mapDispatchToProps = dispatch => ({
  addReview: reviewObject => (
    dispatch({ type: "ADD_REVIEW", payload: reviewObject })
  ),

  deleteReview: id => (
    dispatch({ type: "DELETE_REVIEW", payload: id })
  )

})

export default connect(null, mapDispatchToProps)(ReviewsContainer);
```