How to Use React onClick Events in Class and Functional Components
In this article, we’ll cover the basics of React onClick events and we’ll learn to handle click events in class and functional components. We’ll discuss the differences between JavaScript and React click events, the syntax of event handlers, and binding event handlers to the this keyword. React has many intimidating parts that are harder to grasp for beginners, but the way events are handled in React is simpler and more straight forward than in vanilla JavaScript. In JS, the behavior is separated from the HTML, so if you want to add an onclick event handler on a button element, you first need to select the DOM element, then you need to attach an event listener with the .addEventListener() method. Inside this method, you can call or define another function that will execute when the event is triggered. A simpler approach is to assign an onclick event to a DOM element inline, and to call a function that will execute only when the event fires. In this case, you write a bit less code, but you still need to use a method like .getElementById() inside the function, for selecting the element. When the HTML and JS code are in separate files, finding the right elements and ensuring the correct scope for each function can become quite a challenge. In React, each component has its own markup and methods, and in most cases, there’s no need to add or remove event listeners. You can simply declare the function to be called inside your component, and immediately call it inside the return() method. We’ll look at some practical examples and compare the way JS and React handle click events in the next sections of this article. This article will give you an overview of React onClick event handlers their particularities and differences compared to JavaScript event handlers. By the end of the post, you should know how to handle events in both class and functional components, and how to pass parameters to onClick event handlers. This article explains the React onClick event handler and its uses in functional and class components. To be able to follow the examples, you should be familiar with: If these concepts are new to you, please take a few minutes to read about JS click events first, and check the React documentation for a short intro to JSX and React. Just like HTML/JS, React allows you to call functions and perform actions when a user interacts with the app's interface. These interactions fire events, which can be keyboard events, focus events, touch events, click events, and so on. Click events are triggered when an element is clicked, and are defined in React with the event type onClick . This is passed as an attribute to the element that we want to react to the user's action. What happens after the element is clicked is defined with event handlers, which can be browser actions or JS functions. Although in most cases onClick handlers are used with buttons and links, you can place handlers for click events on any element, including plain text or containers. If we look at the syntax of event handlers, there are two main differences between React and pure JS code. First, React events use camelCase syntax, so instead of writing onclick , we’ll write onClick . Then, if JavaScript functions are used for performing some action when an HTML element is clicked, the event handler calls the function like this: In React, the function is called inside curly braces: This may seem like a small difference, but it’s essential to keep in mind, as calling the function directly in the JSX code means that the value of the function is used in the onClick attribute. So instead of passing a function that can be called every time the user clicks the button, you’re calling it only once, when the component is rendered. In this case, all other clicks on the button will call the result of the function, so there will be no interaction to see, no action to perform. Another difference is that in React the event handler onClick can only receive one function, while in the HTML/JS approach, any number of JS functions can be passed to an onclick event handler. Finally, React events always bubble , while in JavaScript some events - such as onchange for example - do not bubble up. This means that if you have an element or component nested inside a container, and you assign an event handler to the container, when you click the nested element the event will still be captured. This happens even if you don’t directly click the container, because events bubble up to all their parents and ancestors. All modern browsers have event bubbling as their default manner of handling event flows. A consequence of this behavior in React is that if you want to prevent the default propagation of events, you need to call preventDefault() explicitly. Compared to JS, in React you cannot use return false, so you would have to do something like this: We’ll look at this behavior more in-depth in the next sections. Now that you are familiar with the basics, let’s see how event handlers look in class and functional components. For both examples below I’ll use codesandbox.io. In a functional component, the event handler is passed as an attribute to an element or component. This attribute receives a function that describes what happens when the user interacts with the element. Like with any other event, if the user clicks the element multiple times, the event is triggered and the function is called multiple times. Let’s see how this looks in practice. I’ll create a new React file in codesandbox.io, with no additional dependencies. You can find the sample code here . When you run this code, you should see the message ‘Hi there, user!’ logged once in the console. This is the result of <div onClick={greetUser()}> calling the function inside the JSX code. However, if you click the button, the message will log again in the console, because the event calls the greetUser() function defined above. Now, if the div onClick would also call the function instead of the function result, we should see the greeting message logged in the console also when clicking the text. This would be the result of the event bubbling up to the parent container. Let’s see if this works correctly. In the code above, remove the () from <div onClick={greetUser}> . Click the text now, and you should see in the console the message ‘Hi there, user!’ logged again. Moreover, if you click the button now, you should see the message logged twice. This happens because you’re actually triggering two events: one on the button, and one on the div container. Class components handle events in a similar manner, but there are some small differences. Let’s look at an example: You can find the sample code for this example here . Note that the handleClick function is defined outside of the render() method. We can also declare an inline function directly in the onClick attribute, like below: In this case, clicking either one of the nested components - the paragraph or the button - will log the message in the console. Now let’s see how we can prevent the event bubbling behavior with preventDefault() . Let’s say that instead of logging something in the console, we want to redirect the user to another page when the text is clicked. Let’s adjust the code like below: You can find the code for this example here . I did the following changes: first, I’ve replaced the <p> with an <a> , and added the href=” https://google.com ” attribute. So now if we click the text, we should be redirected to Google’s homepage. At the same time, when clicking the link, the ‘Hi there, user!’ message should be logged in the console, because of the event bubbling behavior explained previously. To redirect in this case is the default behavior for the <a> tag, so if we add preventDefault() , the redirect shouldn’t happen anymore, but the greeting message should still be logged. Let’s see if this is what happens. First, we need to adjust the handleClick function as follows: Now if we run the code and click the text, we should see the message logged once in the console. If we click the button, the message will be logged twice. In this example, the e is called a synthetic even t, and it's a cross-browser wrapper around the browser's native event. It has the same interface as native events, so it can make use of the preventDefault() method, as shown above. The advantage of React's events is that they provide cross-browser compatibility, so a React click event behaves the same across all browsers. In class components, it is good practice to declare the function inside the component, as a method. However, if you want to pass props or state later on to the rendered component, you need to bind the event handling function inside the constructor. Here’s an example: It's necessary to bind this inside class components, because they're not bound by default, so if you write <button onClick={greetUser}> , nothing will happen. Try it out, you should get an error that says that greetUser is undefined. Let’s say that instead of logging the message ‘Hi there, user!’ you want to show the user's actual name. You want this to change for every user, so you need a way to pass the name as a parameter to the onClick event handler. You can do this with an arrow function. In this case, the functional component from our previous example could look like this: You can find the code for this example here . In the case of class components, we have to bind the event handler to this , as shown before. Our component will therefore become: You can find the code for this example here . React click events are similar to JS events, with a few differences in syntax and propagation behavior. Event handlers such as onClick can be used in both functional and class components, the former being more straight-forward, while the latter requires the binding of the handlers to this . To learn more about React's event system and how to handle user interactions in a React app, check out lesson 10 in our 30 days of React course .