Can I call multiple event handlers in response to a single event?

Question

Can I call multiple event handlers in response to a single event?

Answer

By passing an anonymous function, or a named function, with multiple event handler calls as the function body, to our event listener (like onClick, onKeyUp, onChange, etc) we can call multiple event handlers in response to a single event.

For example:
Using an anonymous function:

import React from 'react';
import ReactDOM from 'react-dom';

class MyButton extends React.Component {
  eventHandler1() {
    console.log('eventHandler1 called!');
  }

  eventHandler2() {
    console.log('eventHandler2 called!');
  }

  render() {
    return ( 
      <button onClick={() => {
        this.eventHandler1();
        this.eventHandler2();
      }}>Here's a button!</button> // here `onClick` is set to an anonymous function where the function body contains multiple function calls that will be triggered on the click event of the button
    )
  }
};

ReactDOM.render(
  <MyButton />,
  document.getElementById('app')
);

and using a named function:

import React from 'react';
import ReactDOM from 'react-dom';

class MyButton extends React.Component {
  eventHandler1() {
    console.log('eventHandler1 called!');
  }

  eventHandler2() {
    console.log('eventHandler2 called!');
  }

  handleClick = () => {
    this.eventHandler1();
    this.eventHandler2();
  }

  render() {
    return (
      <button onClick={this.handleClick}>Here's a button!</button> // here `onClick` is set to a named function `handleClick` where the function body contains multiple function calls that will be triggered on the click event of the button
    )
  }
};

ReactDOM.render(
  <MyButton />,
  document.getElementById('app')
);
12 Likes

isn’t it necessary here to define a constructor and then bind this to the event handler ?

2 Likes

It depends. If you’re writing code before React version 16, then yes, you’d have to bind each method being used in a class component to this. Also in this example, arrow functions are being used for the event handlers, so the context of this changes, which basically boils down to not having to bind this.

1 Like

How can I pass values to the function if we are not using () while calling?

Example:

class Button extends React.Component {
  scream(m) {
    alert(m);
  }

  render() {
    return <button onClick={this.scream("hello")}>AAAAAH!</button>;
  }
}

This doesn’t work. Why?

1 Like

The way you use onClick={this.scream(“hello”)} you are executing the function and the result will be the value of onClick , to make this work you can create an anonymous function instead

class Button extends React.Component {
  scream(m) {
    alert(m);
  }

  render() {
    return <button onClick={ () => this.scream("hello") }>AAAAAH!</button>;
  }
}
11 Likes

What about receiving multiple events handlers on a child functional component ?do you just say
onClick={props.handleClick} once?

This is SO helpful. Thanks!

Now I get a bit confused.
We are not using parens here; {this.scream}, but this is not a getter function.
Anyone care to explain?

1 Like

The difference lies in whether you are calling a function in the opening tag as the attribute value of the event handler or calling a function between tags

2 Likes

Actually my wording was a bit off earlier on, here is a better explanation:

For event handlers, we do not want to call the function and have the value saved to the event handler, as it would cause the code to break or behave weirdly (eg. when the function returns a function, then the function that is returned will be called in response to the event)
Hence, we do not add brackets to the function which is the attribute value of an event handler.

For functions between tags that are not getter functions, we actually want to call the function and access the returned value, hence brackets should be added

1 Like

Also can I attach more than one event listener to an html element?

In the handleClick function, shouldn’t this be referring to the global object instead, since it’s been declared as an arrow function?

Are you sure this will work? As I recall, the arrow functions’ this always refer to the global object instead…

In case we need to pass a parameter to handleClick, how do we achieve that without causing the page to execute the function when it loads?