DEV Community

Cover image for How to access props in mapDispatchToProps
Emma Goto 🍙
Emma Goto 🍙

Posted on • Originally published at emgoto.com on

How to access props in mapDispatchToProps

Accessing props from state using mergeProps

While using Redux, you may come across a situation where you are passing in props from both mapStateToProps and mapDispatchToProps, and using them together:

// Button.js
const Button = ({ name, setName }) => (
    <button onClick={setName(name)}>Click</button>
);

const mapStateToProps = (state) => ({
    name: getName(state),
});

const mapDispatchToProps = (dispatch) => ({
    setName: (name) => dispatch(setName(name)),
});

export default connect(mapStateToProps, mapDispatchToProps)(Button); 
Enter fullscreen mode Exit fullscreen mode

We can save Button having to know about name, and instead use mergeProps:

// Button.js
const Button = ({ setName }) => (
    <button onClick={setName}>Click</button>
);

const mapStateToProps = (state) => ({
    name: getName(state),
});

const mapDispatchToProps = (dispatch) => ({
    setName: (name) => () => dispatch(setName(name))
});

const mergeProps = (stateProps, dispatchProps) => ({
    setName: dispatchProps.setName(stateProps.name),
});

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(Button); 
Enter fullscreen mode Exit fullscreen mode

What does mergeProps do?

mergeProps is an optional third argument you can pass into connect. As the name suggests, it merges all the props into one object for your component to use. By default, it will look like this:

(stateProps, dispatchProps, ownProps) =>
    ({ ...stateProps, ...dispatchProps, ...ownProps })
Enter fullscreen mode Exit fullscreen mode
  • stateProps are all the props from mapStateToProps - in the above example, name
  • dispatchProps are all the props from mapDispatchToProps - setName
  • ownProps are all props that are passed into a component like this <Button foo={bar}/>

Accessing ownProps in mapDispatchFromProps

We can also access ownProps from mapDispatchToProps. Here we have the same Button example, but instead of name coming from mapStateToProps, this time it’s being passed in from the Form component:

// Form.js
import Button from './Button';

const Form = () => (
    <>
    {/* A bunch of other stuff... */}
    <Button name={'Emma'} />
    </>
);

// Button.js
const Button = ({ name, setName }) => (
    <button onClick={setName(name)}>Click</button>
);

const mapDispatchToProps = (dispatch) => ({
    setName: (name) => dispatch(setName(name)),
});

export default connect(null, mapDispatchToProps)(Button); 
Enter fullscreen mode Exit fullscreen mode

We can use the name prop directly in mapDispatchToProps by using its second argument, ownProps:

const Button = ({ setName }) => (
    <button onClick={setName}>Click</button>
);

const mapDispatchToProps = (dispatch, ownProps) => ({
    setName: () => dispatch(setName(ownProps.name)),
});

export default connect(null, mapDispatchToProps)(Button); 
Enter fullscreen mode Exit fullscreen mode

Even if name is now unused, it will still be passed in as part of ownProps to the Button component. We can filter it out using mergeProps:

const mergeProps = (stateProps, dispatchProps, ownProps) => ({
    ...dispatchProps,
});

export default connect(null, mapDispatchToProps, mergeProps)(Button); 
Enter fullscreen mode Exit fullscreen mode

Pro-tip: Using mapDispatchToProps’ object form

You’ll notice that I always defined mapDispatchToProps in its function form:

const mapDispatchToProps = (dispatch) => ({
    setName: (name) => dispatch(setName(name))
});
Enter fullscreen mode Exit fullscreen mode

If you’re not making use of ownProps or mergeProps, we can actually simplify it down to its object form, which does the exact same thing:

const mapDispatchToProps = {
    setName,
};
Enter fullscreen mode Exit fullscreen mode

Thanks for reading!

Top comments (0)