Redux connect() with multiples actions / states
Asked Answered
U

3

16

What is the proper way of connecting multiple states with corresponding action creators in Redux?

Is that even a good idea?
How can I work around that if it's a stupid idea?

export default connect(

// which part of the Redux global state does
// our component want to receive as props?
(state) => {
  return {
    state: state.instagram
  };
},

// which action creators does
// it want to receive by props?
(dispatch) => {
  return {
    actions: bindActionCreators(instagramActions, dispatch)
  };
}

)(FeedContainer);

What I basically want is something like this:

...
state: {state.instagram, state.facebook}
...

...
const mergedActions = {instagramActions, facebookActions};
actions: bindActionCreators(mergedActions , dispatch)
...
Unpredictable answered 17/2, 2016 at 10:54 Comment(0)
S
20

Using the provided callbacks mapStateTopProps and mapDispatchToProps is the proper way to connect your component with a filtered subset of your state and already bound actionCreators.

To achieve what you want you could simply do:

(state) => {
  const { instagram, facebook } = state;
  return {
    state: { instagram, facebook }
  };
}

and

(dispatch) => {
  return {
     actions: bindActionCreators(Object.assign({}, instagramActions, facebookActions), dispatch)
  };
}

This does not work:

actions: bindActionCreators({instagramActions, facebookActions} , dispatch)

as the method does not support nested objects yet. See code here. It only iterates over the keys and looks for functions.

Within your mapDispatchToProps callback you could leave the extra state layer away

(state) => {
   const { instagram, facebook } = state;
   return {
      instagram, 
      facebook
   };
}

By doing this you can access the props with:

this.props.facebook and this.props.instagram instead of this.props.state.facebook and this.props.state.instagram. But this is only a question of style I think.

There are several ways of binding your state and dispatch to props. In the end it is a question of style. I could provide several different examples of how to do it, but better take a look into the official documentation and find your own style https://github.com/reactjs/react-redux/blob/master/docs/api.md

Syllogize answered 17/2, 2016 at 11:58 Comment(2)
Even if you don't require multiple action creators in your component props, it's wise to stick to one convention across all your components.Eads
how do you call facebookActions from the component then? I used to call this.props.facebookActions but now I get error: _this2.props.facebookActions is not a function...Breathe
T
3

Or you can simple do that:

import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return {
    todoActions: bindActionCreators(todoActionCreators, dispatch),
    counterActions: bindActionCreators(counterActionCreators, dispatch)
  }
}

as shown in react-redux documentation

Transect answered 18/9, 2018 at 8:43 Comment(0)
C
1

I know this is an old question, but in case someone else wants to map all actions into a single key in this.props (like me), I am adding my two cents here.

Expanding on DavinTryon's comment on the accepted answer, another way to achieve "mergedActions" is by using the spread operator, especially if you want to use one key (say, actions) for all actions and call them using this.props.actions.[specificAction]. Here is what you have to do in the connect method:

export default connect(
(state) => {
  return {
    state: state.instagram
  };
},

(dispatch) => {
  return {
    actions: bindActionCreators({...instagramActions, facebookActions}, dispatch)
  };
}

)(FeedContainer);

In case you are declaring the methods separately (with something like mapDispatchToProps and mapStateToProps), you can write your mapDispatchToProps as follows:

const mapDispatchToProps = dispatch => {
  return {
    actions: bindActionCreators({ ...instagramActions, facebookActions }, dispatch)
  };
};

This will map all your action creators in both facebookActions and instagramActions to this.props.actions.

Classicist answered 29/10, 2018 at 10:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.