React’s onClick Event Handler Explained
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>
)
}
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>
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>
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>
);
}
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()}>
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}>
Alternatively, you can also inline the function itself.
<button onClick={() => sendMessage()}>
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>
)
}
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');
}
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>
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>
);
}
}
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.
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.