DEV Community

Chak Shun Yu
Chak Shun Yu

Posted on • Updated on • Originally published at chakshunyu.com

Why I'll definitely use mapDispatchToProps in Redux

Not too uncommon, at my job we make use of Redux in our React frontend stack for state management. A lot of components are connected to the store using Redux's connect and retrieve data from it through mapStateToProps using selectors. Components also need to interact with the store through actions or thunks, which is possible with the dispatch function that connect injects. With those concepts in mind, I've passed along the dispatch function to the component and used it inside its callbacks and lifecycle methods for quite some time now, without ever second guessing this approach. Until recently that is, when I learned about the second argument of the connect function: mapDispatchToProps.

What is mapDispatchToProps?

In short, mapDispatchToProps is a function that maps the dispatch function and returns an object of functions, which will be merged into the existing props and made available to your component as additional ones. It's very similar to mapStateToProps, which maps the state to props for your component, but then for the dispatch function and the values of the return object have to be functions. If you want to learn more about what mapDispatchToProps is and how to use it, you should read the Redux docs as they explain it in quite some detail.

    function mapDispatchToProps(dispatch) {
        return {
            doSomething: () => {
                dispatch(somethingDispatchable());
            },
        };
    }

    class SomeComponent extends React.Component {
        componentDidMount() {
            // Instead of `this.props.dispatch(somethingDispatchable());`
            this.props.doSomething();
        }
        // or...
        render() {
            const { doSomething, ...otherProps } = this.props;
            return <button onClick={doSomething} />;
        }
    }

    export const SomeConnectedComponent = connect(null, mapDispatchToProps)(SomeComponent);
Enter fullscreen mode Exit fullscreen mode

Why use mapDispatchToProps?

First of all, it shares a lot of benefits with mapStateToProps, like making your code more declarative and making sure that Redux related code is more grouped together. The latter might not seem so impactful for mapStateToProps, as it's only responsible for retrieving data from the store. But in the case of mapDispatchToProps, it's definitely something not to overlook as it's responsible for defining the logic of the component's interactions with the store. Logic code has always been difficult to maintain, and keeping related logic together is one way of making this process easier. A concrete example is the introduction of Hooks in React.

It also reduces boilerplate code in your components as less callbacks are required in which dispatch is called and the logic is moved somewhere else. This in turn reduces how bloated your components are, thus resulting into components that are easier to read and maintain. This is especially the case for class components, which are more verbose in general.

However, the main benefit that I see in using mapDispatchToProps is the separation it creates between store related logic and the view of the component and the testing benefits that come with it. Components are not aware anymore of dispatch and thus don't need to know how things have to be done anymore. Rather, all the logic is abstracted away. Which means that the components only see the resulting props and only need to bother with what they do and when to use them. This significantly increases the reusability and testability of the component.

While it's up for debate whether components should be tested with or without the store, there are use cases in which you need the unconnected component or where it makes more sense to test the component without an attached store. In those cases, having mapDispatchToProps means you can more properly and easily test the logic. Rather than mocking the dispatch function and then verifying whether it's called with the appropriate action creator/thunk, in which case you're actually testing implementation details, you can now mock the logic and inject it directly into the component as dependencies.

// Example of how `mapDispatchToProps` makes testing more straightforward.
test('SomeComponent should do something correctly', () => {
  const mockedDoSomething = jest.fn();
  const component = mount(<SomeComponent doSomething={mockedDoSomething} />);
  // Interact with the component to trigger the callback. In this case it's done on mount,
  // but here you would simulate click events if it's attached to a button for example.
  expect(mockedDoSomething).toHaveBeenCalled();
  // Other verifications.
});

Enter fullscreen mode Exit fullscreen mode

Just like the React community, my testing focus is shifting towards verifying behaviour/interactions of my React code, which I've also advocated for to do so at my job. Good practices that allow me to write more proper and meaningful tests in an easier way for my React component have interested me a lot since then. The mapDispatchToProps is a great example of this as it clearly separates Redux related code, the logic, from the React component code, the view. Ultimately, this leads to more reusable and testable components, which is one of the core values of React.

References


After graduation, my career is entirely centered around learning and improving as a developer. I've began working full time as a React developer and I'll be blogging about everything that I encounter and learn during this journey. This will range from improving communicational skills in a technical environment, becoming a better developer, improving technical skills in React and JavaScript, and discussing career related topics. In all of my posts, the focus will be on my personal experiences, learnings, difficulties, solutions (if present), and also flaws.

If you're either interested in these topics, more personalised technical stories, or the perspective of a beginning developer, you can follow me either here or over on Twitter at @Keraito to keep up to date with my posts. I'm always learning, so stay tuned for more stories! 🎉

Top comments (2)

Collapse
 
markerikson profile image
Mark Erikson

Out of curiosity, was there a particular reason why you hadn't been using mapDispatch prior to this?

Also, note that we specifically recommend that you use the "object shorthand" form of mapDispatch rather than the function form:

const mapDispatch = {doSomething : somethingDispatchable};

On the other hand, note that with our new React-Redux hooks API, there's just a useDispatch() hook that gives you access to dispatch.

I talked about some of the differences between connect and the hooks API in my post Thoughts on React Hooks, Redux, and Separation of Concerns and my ReactBoston 2019 talk on Hooks, HOCs, and Tradeoffs.

Collapse
 
keraito profile image
Chak Shun Yu

Not in particular. I never came across the docs for mapDispatch, so I didn't know of its existence. I also didn't see it before in projects that I either worked on or contributed to, so that didn't help either.

I consciously decided to illustrate the function form, because I feel like it better describes what mapDispatch is and what its purpose is. But I definitely like the object shorthand!

While looking into mapDispatch after the first time I learned about it, I also came across useDispatch. I haven't read the links that you mentioned yet (but definitely will do!), but I personally rather stick with the HOC construction. It keeps class and function components interchangeable (at my job we use class components) and I feel like using useDispatch is very similar to just connecting a component and calling the dispatch function, which kind of equals not using mapDispatch. I prefer the explicitness the HOC approach provides in tests and how easy it becomes to validate them.