ReactJS Tutorial for Beginners - 11 - Handling Events


 In this chapter, we will learn how to handle events in React applications.

Handling events basics

Handling events with React elements is very similar to handling events on DOM elements. There are few differences though.
  • React events are named using camelCase, rather than lowercase onClick instead of onclick.
  • We write React event handlers inside curly braces.
  • In the case of React(/JSX), rather than passing a string, we pass a function as the event handler. onClick={buttonClicked} instead of onclick=”buttonClicked()”.
For example, the HTML:
<button onclick=”buttonClicked()”>
   Click the Button!
</button>
is slightly different in React:
<button onClick={buttonClicked}>
   Click the Button!
</button>
  • Another difference is that in order to prevent default behavior to React, we cannot return false. We have to call preventDefault explicitly. For example, the HTML:
// HTML
<button onclick="console.log('Button clicked.'); return false">
 Click Me
</button>
// React 
function handleClick(e) {
    e.preventDefault();
    console.log('Button clicked.');
}

return (
     <button onClick={handleClick}>
         Click me
     </a>
 ); 

Handling onClick Event in the Functional Component Example

Let's create FunctionClick functional component and handle onClick event:
import React from 'react'

function FunctionClick() {
    function clickHandler() {
        console.log('Button clicked')
      }
      return (
        <div>
          <button onClick={clickHandler}>Click</button>
        </div>
      )
}

export default FunctionClick;

Handling onClick Event in the Class Component Example

Let's create ClassClick class component and handle the onClick event:
import React, { Component } from 'react'

class ClassClick extends Component {

  clickHandler() {
    console.log('Clicked the button')
  }

  render() {
    return (
      <div>
        <button onClick={this.clickHandler}>Click Me</button>
      </div>
    )
  }
}

export default ClassClick

Binding Event

For methods in React, the this keyword should represent the component that owns the method.
Let's create EventBind class component with the following code:
import React, { Component } from 'react'

class EventBind extends Component {

  constructor() {
    super()
    this.state = {
      message: 'Hello'
    }
  }

 clickHandler() {
     console.log(this)
     this.setState({message: 'Goodbye'})
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button onClick={this.clickHandler}>Click</button>
      </div>
    )
  }
}

export default EventBind
When you render this component gives you below error in browser:
TypeError: Cannot read property 'setState' of undefined
Without the binding, the this keyword would return undefined.
Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method. We have three-way binding event handlers.

1. Dynamic Binding :

In this, we will call .bind(this) in the render() function.
import React, { Component } from 'react'

class EventBind extends Component {

  constructor() {
    super()
    this.state = {
      message: 'Hello'
    }
  }

 clickHandler() {
     console.log(this)
     this.setState({message: 'Goodbye'})
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
         <button onClick={this.clickHandler.bind(this)}>Click</button>
      </div>
    )
  }
}

export default EventBind
This approach will work, however, the issue with this approach is that any changes in ‘this.state.message’ will result in re-rendering the component again.
This in turn again call ‘this.buttonClicked.bind(this)’ to bind the handler. As a result, a new handler will be generated which will be completely different than the handler used when render() was called the first time.

2. Using Arrow Function

This approach is better than the first one:
import React, { Component } from 'react'

class EventBind extends Component {

  constructor() {
    super()
    this.state = {
      message: 'Hello'
    }
  }

  clickHandler = () => {
    this.setState({message:'Goodbye'})
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button onClick={this.clickHandler}>Click</button>
      </div>
    )
  }
}

export default EventBind

3. Constructor Binding :

This approach is widely used in React applications and you can find this approach in React documentation as well:
import React, { Component } from 'react'

class EventBind extends Component {

  constructor() {
    super()
    this.state = {
      message: 'Hello'
    }
     this.clickHandler = this.clickHandler.bind(this)
  }

 clickHandler() {
     console.log(this)
     this.setState({message: 'Goodbye'})
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button onClick={this.clickHandler}>Click</button>
      </div>
    )
  }
}

export default EventBind
The second and third approaches give good performance hence widely used in React Applications to bind events.

Passing Arguments

Let's discuss how to pass parameters to the event handler in React.
Example: Send "Goodbye" as a parameter to the clickHandler function, using arrow function:
import React, { Component } from 'react'

class EventBind extends Component {

  constructor() {
    super()
    this.state = {
      message: 'Hello'
    }
  }

  clickHandler = (param) => {
    this.setState({message:param})
  }

  render() {
    return (
      <div>
        <div>{this.state.message}</div>
        <button onClick={() => this.clickHandler("Goodbye")}>Click</button>
      </div>
    )
  }
}

export default EventBind

What's Next?

In this chapter, we have learned how to handle events in React with an example. In the next chapter, we will learn how to render elements/components in React based on some condition with an example.


Comments