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')
);
11 Likes

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

1 Like

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.

4 Likes

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>;
  }
}
16 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?

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

1 Like

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

3 Likes

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?

It’s worth mentioning that the arrow function in Class as public class fields syntax is experimental.

More details:

React/Handling Events

1 Like

“this” in the arrow function will always refer to its current surrounding scope which is the “Button” class here.

2 Likes

this code is not working in my codecademy code editor , why?
@aubsrey

when i run this code without anonymous function , alert runs first then it shows a button and then button will not run , why is it happening?

Starting from the exercise proposed, I was trying to put the text in a variable, to reuse it both in the button, and in the alert popup.

I struggled a bit, but I think a could make it. :smiling_face:
I’m not if this is the correct approach, but at least it’s working without any errors.

I’m trying to publish my solution, but it won’t let me save code, it shows a 403 error. :confused:

In summary, I made a function that returns the text.
And then I call two times.
One to add the text in the button.
Another one as a parameter to the method scream, similar to what @meghanakasal99411115 asked and @almujtabamohammed492 did in the examples above.

I’ll try to edit and save the code for a better understanding, if Discuss here let me…

Some people maybe confused with this in the code provided by aubsrey.
In an event, this refers to the element that received the event.
What to know more, this is a good reference:
The JavaScript this Keyword