DEV Community

loading...
Cover image for React’s onClick Event Handler Explained

React’s onClick Event Handler Explained

Fernando Doglio
Technical blogger, book author and maker of software things. In other words, I love writing specially about software.
Originally published at blog.asayer.io ・5 min read

Original author: Felix Gerschau

TLDR

  • The onClick handler allows you to pass a function to a component, which will be executed when it’s clicked.
  • Call e.preventDefault() to prevent native default behavior, like submitting a form.
const App = () => {
  const sendMessage = (e) => {
    e.preventDefault();
    alert('hi');
  }

  return (
    <button onClick={sendMessage}>
      Send message
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

Handling onClick events in functional components

Event handlers are functions that get executed when a given event happens. For example, you can use them to send a message after the user clicks on a button.

You might already know event handlers from plain HTML and JavaScript. Event handlers in React are very similar.

HTML provides us with event handlers like onclick, onchange, onfocus, and many more. We can use them by adding them to the HTML element as an attribute.

<button onclick=”sendMessage();”>
  Send
</button>
Enter fullscreen mode Exit fullscreen mode

We can do the same in React as well. Most of the time, React’s event handlers have the same name as in HTML, but they are written in camelCase. The handlers above would translate to onClick, onChange, and onFocus in React.

<button onClick={sendMessage}>
  Send
</button>
Enter fullscreen mode Exit fullscreen mode

As you can see, it’s not exactly like in the HTML example. First, curly braces ({}) replace the double quotes () used in HTML.

Curly braces are using in JSX syntax to separate the markup from JavaScript.

Everything that’s inside the braces is evaluated as JavaScript. Everything outside of them is the markup that will be rendered.

For a more complete picture, let’s see how the complete component may look like.

const App = () => {
  const sendMessage = () => {
    alert('hi');
  }

  return (
    <button onClick={sendMessage}>
      Send message
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Play around with the code of this example on codepen.

Here we see why we needed to put sendMessage in curly braces. We define the sendMessage function as a variable at the beginning of the component.

A common mistake here is to call the function right away (like in the HTML example).

<button onClick={sendMessage()}>
Enter fullscreen mode Exit fullscreen mode

Instead of calling the function when the button is clicked, it will be called every time the component renders.

We only need to pass down the function itself without calling it.

<button onClick={sendMessage}>
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can also inline the function itself.

<button onClick={() => sendMessage()}>
Enter fullscreen mode Exit fullscreen mode

Note how we call sendMessage in the inlined function. We do this because it’s part of the inlined function, which we don’t call right away.

React’s synthetic events

As you may have already heard, React has a virtual DOM, which is an abstraction layer that React uses to optimize renders and some browser-specific features.

This means that even though the code we write in React looks similar to HTML, it’s not quite the same.

I wrote an article on how this works exactly. You can check it out here.

Just like React adds an abstraction on top of the DOM, it also adds an abstraction layer to events. React’s events are called synthetic events.

Synthetic events are a wrapper around events that improve performance and normalize the events so that they look the same across all browsers.

Such events are passed to the event handlers, like onClick. We can use it to access the value attribute of the button element.

const App = () => {
  const sendMessage = (e) => {
    console.log('value', e.target.value); // output: “value somevalue”
    alert('hi');
  }

  return (
    <button value="somevalue" onClick={sendMessage}>
      Send message
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

React preventDefault()

Accessing the value attribute is usually done when dealing with text inputs and not in combination with onClick.

What you’ll rather encounter in React applications is the following:

const sendMessage = (e) => {
  e.preventDefault();
  alert('hi');
}
Enter fullscreen mode Exit fullscreen mode

We call the preventDefault function in the event handler, which the synthetic event provides. The name already gives away what it does: It prevents the event from executing the default behavior.

To understand this a little better, we need to know the default behavior of different HTML elements.

If the button element is located inside a form element, the default behavior is to submit the form.

This was fine when HTML forms only had one button anyway, but what if you only want to run the code of the onClick function without submitting the form?

In React, we usually solve this by putting e.preventDefault() at the beginning of the event handler.

Alternatively, you could also solve this natively by changing the type attribute of the button:

<button type=”button”>Click me!</button>
Enter fullscreen mode Exit fullscreen mode

Form elements have an even worse default behavior: They refresh the entire page after the onSubmit event—not something you want to happen in a Single Page Application.

Handling onClick events in class components

In the previous section, I only focused on functional components. While this is the easiest way of writing components in React, you'll still encounter components written as JavaScript classes from time to time.

So let's have a look at the previous example as a React class:

class App extends React.Component {
  sendMessage = (e) => {
    e.preventDefault();
    console.log('value', e.target.value); // output: “value somevalue”
    alert('hi');
  };

  render() {
    return (
      <button value="somevalue" onClick={this.sendMessage}>
        Send message
      </button>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the way we handle onClick events in React classes is the same as in functional components. The function sendMessage is now part of the App class, which is why we access it via this.

In case you were wondering why I defined sendMessage as a variable and not as a method of the class: This is to preserve the scope of the class inside the function, which practically means that I will be able to call this.setState inside the function.

Observability for Production React Apps

Debugging React apps in production may be challenging and time consuming. Asayer is a frontend monitoring tool that replays everything your users do and shows how your app behaves and renders for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder.

Asayer Frontend Monitoring

Asayer helps to quickly get to the root cause by reproducing issues as if they happened in your own browser. It also monitors your frontend performance by capturing key metrics such as page load time, memory consumption and slow network requests as well as Redux actions/state.

Happy debugging, for modern frontend teams - Start monitoring your web app for free.

Original author: Felix Gerschau

Discussion (0)