Performances and mergeProps in Redux

Instead of trying to use Redux to solve everything, you might be better off passing down properties from your containers. You can then also bubble up events (via callbacks).

I might implement it like this:

class MessageSender extends React.Component {
  // other stuff

  handleSend() { this.props.sendMessage(this.props); // from mapActionsToProps }

  render() {
      // from mapStateToProps at an appropriate level
      const { user, title, body } = this.props;

      return (
        <div>
          { /* other stuff */ }
          <SendButton onClick={ this.handleSend } />
        </div>
      );
  }
}

If you send the values to the more appropriate level, then let things like buttons just trigger events, you can get a somewhat cleaner implementation.

It's hard to give super specific advice with a somewhat theoretical example, but I do want to point out that is definitely possible to over-use Redux.

I recommend looking at where you need the data for the app (ignoring the actions), then see where you'll already have the data you need, then see where it makes the most sense to dispatch the action from.


You're missing a fourth approach (similar to your mergeProps option): have the parent component pass a bound-up function or callback closure that captures those values, like:

// using bind()
<SendButton onClick={sendMessage.bind(null, user, title, message)}

// or, as an inline arrow function
SendButton onClick={() => this.sendMessage(user, title, message)}

I suppose in theory a fifth approach might be to connect the parent of the SendButton, have it pass a very simple click handler to the button, and let the parent worry about the arguments from its own props (ie, keep the button itself completely presentational, and put the logic in the parent of the button). Actually, I guess that's pretty much the suggestion that @samanime had.

Which approach you use is really up to you. I personally would probably lean towards that last one, just so that it doesn't re-create a function every time there's a re-render. (In particular, I would avoid the mergeProps approach, as that will re-create a function every time the store updates, which will be even more often than the component re-renders.)

I actually addressed your questions about whether accessing state in thunks breaks "uni-directional data flow" in my blog post Idiomatic Redux: Thoughts on Thunks, Sagas, Abstraction, and Reusability. As a summary, I don't think it actually does break that unidirectional flow, and my opinion is that accessing state in thunks is a completely valid approach.

As a side note, I generally recommend that people use the object shorthand argument for binding methods with connect, instead of writing an actual mapDispatchToProps function:

const mapDispatch = {
    onClickSend : actions.sendMessage
};

export default connect(mapState, mapDispatch)(MyComponent);

To me, there's almost never a reason to actually write out a separate mapDispatch function (which I also talk about in my post Idiomatic Redux: Why Use Action Creators?).