Events in ReactJS

Handeling events in ReactJS is very easy. You can add events like click, change, keydown etc easily by just adding it to the JSX element.

when you add an event, name of the event should be in the camelCase e.g. onClick, onKeyDown, onChange, onKeyPress etc.

In ReactJS, you don't need to use addEventListener to add event on an element. Let us have a look at an example.


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

class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        counter: 0
      };
      this.handleClick = this.handleClick.bind(this);
    }
    handleClick(e){
      e.preventDefault();
      const { counter } = this.state;
      this.setState({
        counter: counter + 1
      });
    }
    render(){
        const { counter } = this.state;
        return (
          <div>
            <div>Total Clicks : {counter}</div>
            <button onClick={this.handleClick}>Increase counter</button>
          </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
                    

Open above code in codepen.

Add events in ReactJS

To add an event in ReactJS, add event name on JSX element on which event needs to be added and assign event listener.

In above example, we have added onClick event on button and assigned event listener handleClick.

Bind event listener to a component

In ReactJS, when you add an event, you are just assigning the event listener like onClick={this.handleClick}.

Now In JavaScript class, methods are not bound by default. You need to specifically bind it. If you forget to bind the method, this will be undefined.
In above example, we have bind the method in constructor() with this.handleClick = this.handleClick.bind(this); statement.

There are four ways to bind an event listener.

Bind in constructor

We already have bound event listener in constructor() in our example. This is the most used and advisable way.

Arrow function

You can use the arrow function while creating the event listener. Let us have a look at an example.


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

class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        counter: 0
      };
    }
    handleClick = (e) => {
      e.preventDefault();
      const { counter } = this.state;
      this.setState({
        counter: counter + 1
      });
    }
    render(){
        const { counter } = this.state;
        return (
          <div>
            <div>Total Clicks : {counter}</div>
            <button onClick={this.handleClick}>Increase counter</button>
          </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
                    

But to use the arrow function, you must be using experimetal public class fields syntax. If you have used create react app, this syntax is default enabled.

Arrow function in callback

You also can use the arrow function in a callback. Let us have a look at an example.


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

class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        counter: 0
      };
    }
    handleClick(e){
      e.preventDefault();
      const { counter } = this.state;
      this.setState({
        counter: counter + 1
      });
    }
    render(){
        const { counter } = this.state;
        return (
          <div>
            <div>Total Clicks : {counter}</div>
            <button onClick={(e) => this.handleClick(e)}>Increase counter</button>
          </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
                    

But this way has two problems.

  • Whenever component re-renders, a new callback is created.
  • If you pass a callback as props to a child component, child component might do some extra re-rendering and that would cause performance issues.

So it would be better to use bind in constructor or arrow function in event listener.

bind() in event

You can use Function.prototype.bind function to bind the event listener. Let us have a look at an example.


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

class App extends React.Component{
    constructor(props){
      super(props);
      this.state = {
        counter: 0
      };
    }
    handleClick(e){
      e.preventDefault();
      const { counter } = this.state;
      this.setState({
        counter: counter + 1
      });
    }
    render(){
        const { counter } = this.state;
        return (
          <div>
            <div>Total Clicks : {counter}</div>
            <button onClick={this.handleClick.bind(this)}>Increase counter</button>
          </div>
        );
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
                    

In this way, you can directly bind the event listener when you assign it to the event. But event listeners will be bound whenever component renders.

So it would be better to use bind in constructor or arrow function in event listener.

Conclusion

In this section, we learned about event in ReactJS and how to bind events in ReactJS.
In the next section, you will learn about how to pass arguments to event listeners in ReactJS.