14

All:

I wonder if it is possible that binding multiple event handlers to same event?

For example:

var LikeToggleButton = React.createClass({
    render: function(){
        (function toggle(){
            this.setState({liked:!like});
        }).bind(this);
        return (
            <div onClick={toggle}>TOGGLE LIKE</div>  
        );
    }
});

Until this point everything seems normal, but I want to add another feature to that button, which is decide by other option:

For example, I have another switch component(could be anything like checkbox or radio button etc.) called "count toggle", which when enabled, the LikeToggleButton's button will be added another onClick handler which is start counting times of button clicked, I know it could be predesignd into the toggle function, but I just wonder if there is a way to append this part to onClick handler?

Thanks

Kuan
  • 11,149
  • 23
  • 93
  • 201
  • Possible duplicate of [Multiple event handlers for the same event and element with Reactjs](http://stackoverflow.com/questions/30054840/multiple-event-handlers-for-the-same-event-and-element-with-reactjs) – XML Dec 07 '15 at 04:57
  • Does this answer your question? [Call multiple functions onClick ReactJS](https://stackoverflow.com/questions/26069238/call-multiple-functions-onclick-reactjs) – Krisztián Balla May 05 '20 at 12:52

4 Answers4

8

If you want to have multiple callbacks executed when onClick is triggered, you can have them passed from outside, so you'll have access to them in the props object. Then execute them all (note: code not tested):

var LikeToggleButton = React.createClass({

    toggle: function() {
        this.setState({liked:!like});
    },

    handleClick: function(e) {
        e.preventDefault();
        this.toggle();
        for (var i=0, l<this.props.callbacks.length; i<l; i++) {
           this.props.callbacks[i].call();
        }
    },

    render: function() {            
        return (
            <div onClick={this.handleClick}>TOGGLE LIKE</div>  
        );
    }
});

BUT, if you want to have components connected between them, you should not do that by calling methods inside handlers. Instead you should use an architectural pattern, where Flux is the obvious choice (but there are lots more).

Take a look to Flux, and here you have more choices.

zhulien
  • 5,145
  • 3
  • 22
  • 36
gontrollez
  • 6,372
  • 2
  • 28
  • 36
  • Thanks, this is good idea, one thing to clear: in this.props.callbacks, how do I know which function is newly added for CLICK event? – Kuan Oct 28 '15 at 21:22
  • Each time the component is rendered it receives a new `callbacks` array so that does not matter. – gontrollez Oct 28 '15 at 21:25
  • Thanks, I am pretty new to React. Where should I put that callbacks array? – Kuan Oct 28 '15 at 21:27
  • you pass it when creating the component: . I recommend you read the react docs carefully. – gontrollez Oct 28 '15 at 21:32
  • Thanks, I mean if I append new handler function(it could be handler for click or for others) in callbacks, how do I know it is for click event? So I guess I should ask should there are multiple callback arrays for dedicated event handling? – Kuan Oct 28 '15 at 22:09
2

For an extensible way that does't require the component to know about components that use it - save the onClick event before changing it. This is highlights extracted from the actual working code:

button.jsx

class Button extends React.Component {

  constructor(props) {
    super(props);
    this.state= { callback: false};
  }

  click(){
    //do stuff here
    if(this.state.callback) { this.state.callback.call(); }
  }

  render () {
    this.state.callback = this.props.onClick; // save the onClick of previous handler

    return (
      <button { ...this.props } type={ this.props.type || "button" } onClick={ this.click.bind(this) } className = this.props.className } >
        { this.props.children }
      </button>
    );
  }
}
export default Button;

Then in another component you can use the button and it can have it's own onClick handler:

class ItemButtons extends React.Component {
  itemClick () {
    //do something here;
  }

render () {
    const buttons = [
      (
          <Button onClick={ this.itemClick.bind(this) } className="item-button">
            <span>Item-Button</span>
          </Button>
      )
    ];

    return (<section>{ buttons }</section>);
}

export default ItemButtons;
David Fridley
  • 165
  • 1
  • 10
-2

Maybe you can set multiple click event handlers on the same one target as described here: https://gist.github.com/xgqfrms-GitHub/a36b56ac3c0b4a7fe948f2defccf95ea#gistcomment-2136607

Code (copied from linke above):

<div style={{ display: 'flex' }}>
    <div style={{
            width: '270px',
            background: '#f0f0f0',
            borderRight: "30px solid red",
            minHeight: ' 500px',
            maxHeight: '700px',
            overflowX: 'hidden',
            overflowY: 'scroll',
        }}
        onClick={this.state.ClickHandler}
        onClick={this.stateHandleClick}
        className="sidebar-btn"
        >
        <button onClick={this.props.ClickHandler}>props</button>
        <button onClick={(e) => this.props.ClickHandler}>props</button>
        <button onClick={this.props.ClickHandler}>props</button>
        <button onClick={this.state.ClickHandler}>state</button>
 //...
</div>
Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
-2

To group multiple actions on an event

onMouseDown={(e) => { e.stopPropagation(); alert('hello'); }}
R.Meredith
  • 184
  • 2
  • 10