Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is mapDispatchToProps?

I was reading the documentation for the Redux library and it has this example:

In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.

This actually makes no sense. Why do you need mapDispatchToProps when you already have mapStateToProps?

They also provide this handy code sample:

const mapDispatchToProps = (dispatch) => {   return {     onTodoClick: (id) => {       dispatch(toggleTodo(id))     }   } } 

What is this function and why it is useful?

like image 319
Code Whisperer Avatar asked Sep 09 '16 20:09

Code Whisperer


1 Answers

I feel like none of the answers have crystallized why mapDispatchToProps is useful.

This can really only be answered in the context of the container-component pattern, which I found best understood by first reading:Container Components then Usage with React.

In a nutshell, your components are supposed to be concerned only with displaying stuff. The only place they are supposed to get information from is their props.

Separated from "displaying stuff" (components) is:

  • how you get the stuff to display,
  • and how you handle events.

That is what containers are for.

Therefore, a "well designed" component in the pattern look like this:

class FancyAlerter extends Component {     sendAlert = () => {         this.props.sendTheAlert()     }      render() {         <div>           <h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>           <Button onClick={sendAlert}/>         </div>      } } 

See how this component gets the info it displays from props (which came from the redux store via mapStateToProps) and it also gets its action function from its props: sendTheAlert().

That's where mapDispatchToProps comes in: in the corresponding container

// FancyButtonContainer.js  function mapDispatchToProps(dispatch) {     return({         sendTheAlert: () => {dispatch(ALERT_ACTION)}     }) }  function mapStateToProps(state) {     return({fancyInfo: "Fancy this:" + state.currentFunnyString}) }  export const FancyButtonContainer = connect(     mapStateToProps, mapDispatchToProps)(     FancyAlerter ) 

I wonder if you can see, now that it's the container 1 that knows about redux and dispatch and store and state and ... stuff.

The component in the pattern, FancyAlerter, which does the rendering doesn't need to know about any of that stuff: it gets its method to call at onClick of the button, via its props.

And ... mapDispatchToProps was the useful means that redux provides to let the container easily pass that function into the wrapped component on its props.

All this looks very like the todo example in docs, and another answer here, but I have tried to cast it in the light of the pattern to emphasize why.

(Note: you can't use mapStateToProps for the same purpose as mapDispatchToProps for the basic reason that you don't have access to dispatch inside mapStateToProp. So you couldn't use mapStateToProps to give the wrapped component a method that uses dispatch.

I don't know why they chose to break it into two mapping functions - it might have been tidier to have mapToProps(state, dispatch, props) IE one function to do both!


1 Note that I deliberately explicitly named the container FancyButtonContainer, to highlight that it is a "thing" - the identity (and hence existence!) of the container as "a thing" is sometimes lost in the shorthand

export default connect(...) ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

syntax that is shown in most examples

like image 192
GreenAsJade Avatar answered Oct 05 '22 04:10

GreenAsJade