DEV Community

Ahmad Jamaly Rabib
Ahmad Jamaly Rabib

Posted on • Edited on

React Event Handling

Hello there! 👋 We are going to learn about React Event handling today.

We know about the html event handling with Html and JavaScript. React does this event handling in a similar but kind of different way. We are going to deep dive on it today. 😁

Difference between HTML and React Events

First let's see how we do it in HTML and JavaScript. We created a simple button with a click event and once the button is clicked it will show in the browser console.

<button onclick="handleClick()">Click</button>

<script>
  function handleClick() {
    console.log("You have clicked the event");
  }
</script>
Enter fullscreen mode Exit fullscreen mode

Button click event

We will do the same thing for React now. We will use our previous code for state and will remove the props locale we passed from the App to Clock component.

function App() {
  return (
    <Clock />
  )
}
Enter fullscreen mode Exit fullscreen mode

We will change the Clock locale based on the click event now. 💪🤗

Now let's create a button in React. 🎉🎊😁
Let's open our Clock component and update in the render method.

  render() {
    const { date } = this.state;
    return (
      <div>
        <h1 className="heading">
          <span>Hello <span>{this.props.children}</span> { date.toLocaleTimeString('en-US')}</span>
        </h1>
        <button>Click here</button>
      </div>
    );
  }
Enter fullscreen mode Exit fullscreen mode

React Button

We can see that we have added a button. But the button isn't functional yet. So there is no event handling there yet. Let's work on it and find out the differences with html button click events. 😊

<button onClick={}>Click here</button>
Enter fullscreen mode Exit fullscreen mode

We are adding an onClick event on the React button. Now let's see our html button onclick event.

<button onclick="handleClick()">Click</button>
Enter fullscreen mode Exit fullscreen mode

Here we can clearly see that we are calling a string "handleClick()" not the function handleClick() on the html button click.

So why are calling a string?

This is because of not calling the handleClick() function when the page is loaded. But the handleClick() function will only be called when we click the button. Because that time the onclick event will trigger the handleClick() function.

Note that, in case of React events we need to write camelcase event. Like we are using onClick for React not onclick like we used for html events.

Also we are not calling string in React. We will call functions inside the curly braces onClick={}. Now let's create a handleClick function inside our Clock class component.

handleClick() {
  console.log("The button is clicked");
}
Enter fullscreen mode Exit fullscreen mode

And in our onClick event let's call the handleClick function.

<button onClick={this.handleClick}>Click here</button>
Enter fullscreen mode Exit fullscreen mode

We are using this.handleClick because it is inside the Clock class component. As the handleClick method is inside the class component we have to use this to call that method.

But we found another difference with the html event call with React. Look below codes

HTML => onclick="handleClick()"
React => onClick={this.handleClick}

In React we are not calling the handleClick function like HTML.

The reason is in HTML we are actually calling string but in React we are not calling the string.

So, in the case of React we directly call the handleClick function. It will actually call during page load. Not during the click event. 🤔

Let's go to the browser now and check.

Updated Click Event

So we can see that the handleClick function is working and the log message is showing.

Handling Default behavior

Let's think about a html link. It has a default behavior to go to the link provided. Let's see an example.

<a href="test.html">Click this</a>
Enter fullscreen mode Exit fullscreen mode

We can see here that this is a link and when we click it will go to the test.html url. We can change this default behavior using return false; with the onclick event.

<a href="test.html" onclick="console.log('You have clicked the event'); return false;">Click here</a>
Enter fullscreen mode Exit fullscreen mode

After updating we can see that this is no longer going to the url and we can see the log message Link is clicked in the console.

But in React we can not use return false; to prevent the default behavior inside DOM.

We can also prevent the default behavior using the preventDefault function when the event will be passed as parameter in JavaScript. And we can use this technique in React events also to prevent default behavior.

Let's go to our React project now. We can see that we have called the this.handleClick function. This handleClick function will actually get the event as a parameter. So we can write this function as handleClick(e) here e is the event. And then we will call the e.preventDefault()function to prevent the default behavior of that event.

  handleClick(e) {
    e.preventDefault();
  }
Enter fullscreen mode Exit fullscreen mode

Now even if we change the button to link or submit button the default behavior will be prevented and we will only see what is inside the handleClick function.

<a type="button" href="test.html" onClick={this.handleClick}>Click here</a>

<button type="submit" onClick={this.handleClick}>Click here</button>
Enter fullscreen mode Exit fullscreen mode

Update locale using React state and click event

Now, let's update the functionality of the handleClick function so that it can change the locale of the Clock when we click the button.

Let's first create a React state locale and set default to bn-BD. And update in our render function.

state = {date: new Date(), locale: 'bn-BD'}

render() {
  const { date, locale } = this.state;
  return (
    <div>
      <h1 className="heading">
        <span>Hello <span>{this.props.children}</span> { date.toLocaleTimeString(locale)}</span>
      </h1>
      <button type="submit" onClick={this.handleClick}>Click here</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

We have changed to date.toLocaleTimeString(locale) from date.toLocaleTimeString('en-US').

And now let's update in our handleClick function and check in the browser.

  handleClick(e) {
    e.preventDefault();
    this.setState({
      locale: 'en-US'
    });
  }
Enter fullscreen mode Exit fullscreen mode

handleClick setState

Oh no! We got an error! 😭😱 It is saying Uncaught TypeError: Cannot read properties of undefined (reading 'setState')
But this didn't happen in our tick method. Why is it happening here? Let's find out.

So here the problem is we are getting this as undefined. Why is that?

Actually, here we are using the Clock component which is a class component. We might know that class is a blueprint of the object. So here we have this which is the object of the Clock class. By using this we can access all the properties of the Clock class.

So here in the render method when we use this.handleClick it is calling the handleClick method without any issues. But inside the handleClick method this isn't passed, just the reference is passed.

So what happens here is, After the click event this isn't instantly calling the handleClick function. Here it is just a callback function.

When the callback function is called, it can't find this that time. That's why we are getting this as undefined.

Fixing this issue

There are several ways to fix the this issue in the class component. Let's try to fix it now. 🎉🥳

1. Making handleClick method as arrow function.

Let's update our handleClick method to an arrow function.

 handleClick = (e) => {
    e.preventDefault();
    this.setState({
      locale: 'en-US'
    });
  }
Enter fullscreen mode Exit fullscreen mode

We can do a console.log(this) inside the handleClick method to check this.

Arrow function

We can see that there is no error and we have successfully updated the state of locale to "en-US".

The reason why the arrow function works but the traditional function not working is because the arrow function doesn't use additional scope for it. So it didn't change this inside the function. Where our normal function has its own scope, so we couldn't access this inside our normal function.

This is one of the main reasons we use arrow functions in such cases.

2. Using bind

If we don't want to use the arrow function (although that is recommended) we can use bind to use this inside the handleClick function.

We need to create a constructor function and update it there.

constructor(props) {
    super(props);
    this.state = {date: new Date(), locale: 'bn-BD'}
    this.handleClick = this.handleClick.bind(this);
  }
Enter fullscreen mode Exit fullscreen mode

And keep the onClick event function same as before.

onClick={this.handleClick}
Enter fullscreen mode Exit fullscreen mode

So that's it!

We are doing the same thing inside the constructor. The bind method binds our object inside the handleClick method so we can access it inside the handleClick method.

So in the constructor we are telling that the this.handleClick is not the full function. this.handleClick means this.handleClick.bind(this) function where we are binding this and passing to handleClick function.

3. Passing Parameters to handleClick function
In this case we actually need to update where we are calling the function in the onClick event. We can actually do this. Instead of adding a constructor.

onClick={this.handleClick.bind(this)}
Enter fullscreen mode Exit fullscreen mode

Also we can pass parameters from this onClick event.

onClick={this.handleClick.bind(this, 'en-US')}
Enter fullscreen mode Exit fullscreen mode

By using this bind we can easily pass the parameters.
So the handleClick method can be updated to

handleClick(locale) {
    this.setState({
      locale
    });
  }
Enter fullscreen mode Exit fullscreen mode

Easy right! 😁🤗

React Event Handling

Also there is another way if we want to use arrow function on the onClick event.

onClick= {() => this.handleClick('en-US')}
Enter fullscreen mode Exit fullscreen mode

Arrow function on onclick event

This one is more easier! yay! 😁😄

That's all about event handling in React today. Thank you for reading. 🙏😊

Here is the github repository for todays code.

I might come out tomorrow with some new topics. Till then goodbye! 👋🙏🙌

Top comments (0)