Dev Man
Dev Man

Reputation: 71

bindActionCreators called on a dispatch

I was under the impression that the purpose of bindActionCreators was to wrap actionCreators in a dispatch function, and give these new functions a name (which could be passed to components as props, via mapDispatchToProps and connect).

However, a tutorial I found seemed to call bindActionCreators on a dispatch function (updatePerson), which seems to violate the whole point of bindActionCreators.

actions/update_person.js

import { UPDATE_PERSON } from './types';

export default function updatePerson(person) {
  return dispatch => {
    dispatch(updatePersonAsync(person));
  }
}

function updatePersonAsync(person){
  return {
    type: UPDATE_PERSON,
    payload: person
  };
}

components/WantedCard.js

//connects redux actions to props
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    updatePerson: updatePerson,
    deletePerson: deletePerson
  }, dispatch);
}

What exactly am I getting wrong here, with my understanding? UpdatePerson is already bound(?)

This is the tutorial repo: https://github.com/lorenseanstewart/redux-wanted-list and blog post https://lorenstewart.me/2016/11/27/a-practical-guide-to-redux/

Upvotes: 2

Views: 579

Answers (1)

Sagiv b.g
Sagiv b.g

Reputation: 31024

UpdatePerson is already bound(?)

No it wasn't it's just a normal function that you import.
In order to make it play with the redux flow cycle you need to dispatch this function.

When you are not passing mapDispatchToProps you get the dispatch function as a prop to your connected component, so to use it you would have to do it like this:

this.props.dispatch(updatePerson())

If you do decide to pass mapDispatchToProps to connect then you will not receive dispatch as a prop but you could wrap your actions with it:

const mapDispatchToProps = dispatch => {
  return {
    updatePerson: () => {
      dispatch(updatePerson())
    }
  }
}

Or you can just pass an object:

const mapDispatchToProps = {
    updatePerson,
    deletePerson
}

Another way is to use bindActionCreators (like you mentioned in your post) With this approach you can dispatch the action with this line of code:

function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    updatePerson: updatePerson,
    deletePerson: deletePerson
  }, dispatch);
}

And call it like this:

this.props.updatePerson()

Note that you can use the Shorthand property names of ES2015 if the key matches the variable

function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    updatePerson,
    deletePerson
  }, dispatch);
}

Another nice approach with bindActionCreators is to import all actions as alias (even different actions from different files):

import * as userActions from '../url'; 
import * as otherActions from '../otherUrl';

And then stack them all in one object (or separate them if you want):

function mapDispatchToProps(dispatch) {
    const combinedActions = { ...userActions, ...otherActions };
    return {
        actions: bindActionCreators(combinedActions, dispatch)
    };
}

Now you can refer any action via the actions object:

this.props.actions.myAction();
this.props.actions.myOtherAction();

You can read me about the various options in the docs

Upvotes: 1

Related Questions