how to `bindActionCreators` with redux-thunk
Asked Answered
A

3

6

I am quite new to JavaScript and react-native and I have existing project that I need to add functionality to. It is using redux and redux-thunk with redux-saga to send API requests. Currently it supports only 1 dispatch function per component and I need to dispatch several types of requests to the saga. I am trying to bindActionCreators to add the dispatch to the stores but to no avail.. I am totally lost on the mapDispatchToProps part and how do I "fire the action" afterwards..

in single dispatch to props, I did this:

let sdtp = (arg) => {
   return (dispatch) => {
     dispatch({
       type: 'GET_TEST_HASHMAP_SAGA',
       hashmap: arg
     })
   }
 }

export default MainPage = connect(
   mapStateToProps,
   { sdtp }
)(MainPage);

and I can "access the function" (is this the right term? at least my saga gets called) inside the MainPage.render() component :

`this.props.sdtp({'hello':'world'});`

but when I change to use bindActionCreators, I cannot access it in the props anymore (I have tried so many different experiments I almost give up)

Here is how I construct my multiple dispatches:

let action1 = (args) => {
   return (dispatch) => {
      dispatch({
         type: 'GET_TEST_HASHMAP_SAGA',
         hashmap: arg
      });
   }
}

let action2 = (args) => {
   return (dispatch) => {
      dispatch({
         type: 'GET_TEST_HASHMAP_SAGA2',
         params: arg
      });
   }
}

let action3 = (args) => {
   return (dispatch) => {
      dispatch({
         type: 'GET_TEST_HASHMAP_SAGA3',
         args: arg
      });
   }
}

let mdtp = (dispatch) => {
  return {
    actions: bindActionCreators(action1, action2, action3, dispatch)
  }
}

export default MainPage = connect(
   mapStateToProps,
       { mdtp }
)(MainPage);

I am trying to access the actions like this:

this.props.mdtp.action1({arg: 'hello'});

Thanks in advance!

Announce answered 18/11, 2017 at 2:6 Comment(0)
S
9

connect takes four arguments...most people usually only need the first two.

mapStateToProps you have, and I'm assuming it's a function.

mapDispatchToProps is the second...the issue is there.

bindActionCreators is nothing but a for loop...leave it out and you will better understand what is happening.

Try this:

function mapDispatchToProps(dispatch) {
  return {
     action1: (args) => dispatch(action1(args)),
     action2: (args) => dispatch(action2(args)),
  }
}

 export default MainPageContainer = connect(
   mapStateToProps,
   mapDispatchToProps
 )(MainPage)

And call them as this.props.action1(args) and this.props.action2(args)

If you insist on using the overrated bindActionCreators the syntax would be:

 function mapDispatchToProps(dispatch){
   return {
     actions: bindActionCreators({
       action1,     
       action2,
     }, dispatch)
   }
 }

Also, use const instead of let since you are not redefining the value. It is also best to export the connected component under a different name than the class name of the component.

Stein answered 18/11, 2017 at 4:59 Comment(2)
thanks for the explanation! I didn't know the other way at all, googling just show the bindActionCreators and I thought it is the only way, lol.. btw, I tried your bindActionCreators way, it doesn't work, the one from @magneticz which return the result of bindActionCreators directly works thoughAnnounce
There's a typo in this answer. "mapDispathToProps" should be "mapDispatchToProps". I tried editing, but edits must be at least 6 characters. Commenting so those who copy paste the final code block don't get frustrated.Isiahisiahi
C
2

In your mpdt function, you need to return result of bindActionCreators call, not object with action key.

So, it should be

const mdtp = (dispatch) => {
  return bindActionCreators({
    action1, action2, action3
  }, dispatch);
};

and you can call them as this.props.action1(...)

From your code it also seems, that you have confused two ways of passing action creators to the component. One way is described above. And another way, you can pass your action creators directly to connect() using object notations, like so

export default MainPage = connect(
   mapStateToProps,
   { action1, action2, action3 }
)(MainPage);

which will have same result. And your first approach, with sdtp action creator uses this approach.

Catatonia answered 18/11, 2017 at 5:3 Comment(1)
thanks! I was blinded by the thunk, so many params and function inside function, I didn't know that you can just { x, y, z } together everything. This is another good answer but sorry that I have accepted an answer just..Announce
C
1

Alternatively, you can also skip mapDispatchToProps entirely..

Within your render() function, you can just call dispatch directly like this:

this.props.dispatch({type: 'GET_TEST_HASHMAP_SAGA2', params: {"hello": "world"}});

Then in your connect function, you can skip the mapDispatchToProps param entirely.

export default MainPage = connect(
   mapStateToProps
)(MainPage);

I know this isn't the answer, but this is just an alternative that works as well

Catastrophe answered 18/11, 2017 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.