Introduction
Events usually represent some type of interaction between the user and the app - any time a user clicks on the object, types in the input field, drag or drop some element, and so on. Therefore, each event usually requires some type of reaction from the app. Each time a significant event occurs, we, as programmers, can define a function used to respond to the occurred event. Those functions are called event handlers, and they are the core of event management in any programming language. Event management is a set of techniques used to handle events.
React is no different! In this guide, we'll be digging deeper into the concept of event management in React. We'll take a look at several different types of events, as well as mechanisms used to handle those events.
Differences Between DOM and React Event Handling
If you are using React, you are probably already familiar with DOM events in JavaScript:
<!- JavaScript event ->
<button onclick="handleClick()">
Trigger Function
</button>
This is the onclick
DOM event. When this example button is clicked the handleClick()
function is called - that's the basic principle of the event management. That basic idea is shared between JavaScript and React, but there are a couple of nuances differentiating the two of them.
First of all, there is a minor difference in the event naming - React uses camel case names instead of lowercase names used by JavaScript. After a quick look at the previous example, you will notice the name of the event is onclick
, and the React alternative is onClick
. Furthermore, React makes use of JSX (JavaScript XML), which allows us to pass a function as the event handler (inside curly braces) rather than a string:
<!- React event ->
<button onClick={handleClick}>
Trigger Function
</button>
Note how we didn't call the handleClick
function inside curly brackets - calling it by {handleClick()}
will call the handler function each time an element is rendered. The syntax we've used ensures the handler function is called only when the event is registered.
Oftentimes you'll find yourself in the situation where you want to prevent the default behavior after the event is registered. For example, the onsubmit
JavaScript event is registered after a user clicks the submit button. The default behavior is to send form data appropriately and reload the web page, but we might need to prevent reloading the page. JavaScript has a handy trick for preventing the default behavior up in its sleeve:
<form onsubmit="console.log('You clicked submit.'); return false">
<button type="submit">Submit</button>
</form>
We've defined the handler function in the usual way, but notice how we've added return false
after the handler function definition. That's the way JavaScript developers prevent the default behavior when handling events. If you don't put return false
after the handler function in this example, the page will reload before the console even gets a chance to log the message.
Note: An event handler function can be defined in a JavaScript file, and called in HTML when an event is detected. Alternatively, you can also define and call the handler function directly in HTML code (as you can see in the example above).
React simply doesn't support this trick! To prevent default behavior in React, you must explicitly call preventDefault
:
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log("You clicked submit.");
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
Maybe not as simple as event handling in JavaScript, but certainly a more robust way to handle events. This example illustrates the event handling in use with a functional component in React. We've simply declared a handler function in the component, and called it within the return()
method.
Note: React takes care of the cross-browser compatibility, so you don't need to worry about that!
Handling Events in Functional Components
The event handler is passed as an attribute to an element or component in a functional component. When the user interacts with the element, this attribute receives a function that describes what happens.
Handling onClick Event
If the user clicks the element multiple times, the onClick
event is triggered and the function is called multiple times, just like any other event. Let’s see how this looks in practice, we would create a button and call a function:
const App = () => {
const handleClick = () => {
console.log("This function has been triggered!");
};
return (
<div className="App">
<h1>Hello World</h1>
<button onClick={handleClick}>Trigger Function</button>
</div>
);
};
This will log out “This function has been triggered!” in the console.
Passing Parameters Into Events
If we want to pass parameters or values to the function that is being triggered, we must use an arrow function or an actual function. In our case, let’s say we want to pass a value to the function and then log it in the console:
const App = () => {
const handleClick = (name) => {
console.log("My Name is:", name);
};
return (
<div className="App">
<h1>Hello World</h1>
<button onClick={() => handleClick("John Doe")}>
Trigger Function
</button>
</div>
);
};
This will display “My Name is: John Doe” in the console. We can also make use of an actual function using the function keyword and everything will still work perfectly:
<button onClick={function(){handleClick('John Doe')}}>Trigger Function</button>
Handling onSubmit Event
We can also handle form submit events with React when a user clicks the submit button or taps the enter key on the keyboard. This is handled similarly to the onClick
event:
const App = () => {
const handleSubmit = () => {
console.log("The submit button was clicked!");
};
return (
<div className="App">
<h1>Hello World</h1>
<form onSubmit={handleSubmit}>
<label>Name</label>
<input type="text" />
<button type="submit">Submit</button>
</form>
</div>
);
};
"The submit button was clicked!" will be logged out as a result of this. However, because the browser will immediately reload, we will use the preventDefault()
method to prevent the browser from performing the default action.
const handleSubmit = (e) => {
e.preventDefault();
console.log("The submit button was clicked!");
};
Handling Events in Class Components
Class components handle events similarly to functional components, with a few minor differences. Let's create a button which calls the handleClick
function when clicked:
class App extends React.Component {
handleClick = () => {
console.log("This function has been triggered!");
};
render() {
return (
<div className="App">
<h1>Hello World</h1>
<button onClick={this.handleClick}>Trigger Function</button>
</div>
);
}
}
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Note: We have to use this
keyword because we are in the App
class, and the handleClick
is one of the member functions of that class.
Passing Parameters Into Events
It is best practice to declare the handler function as a method within the class component. If you want to pass parameters, props, or states to the rendered component later, you must bind the event handling function to this
inside the constructor.
Let's say we have a state value set that we want to change when a specific button is clicked and we want to use the passed parameter, we'd have something like this, but it would throw an error:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
title: "Welcome, We are glad you are here!"
};
}
handleClick = (name) => {
console.log("This function has been triggered!", name);
this.setState({
title: `Hello ${name}!`
});
};
render() {
return (
<div className="App">
<h1>{this.state.title}</h1>
<button onClick={this.handleClick("Joel")}>
Trigger Function
</button>
</div>
);
}
}
To solve the issue, we either use arrow functions or Function.prototype.bind]
to bind the this
keyword:
<button onClick={() => this.handleClick("John Doe")}>Trigger Function</button>
<button onClick={this.handleClick.bind(this, "John Doe")}>Trigger Function</button>
Handling onSubmit Event
We can also handle all types of events with class components, as long as we use the this
keyword instead of function when declaring the methods:
class App extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
console.log("The submit button was clicked!");
};
render() {
return (
<div className="App">
<h1>Hello World</h1>
<form onSubmit={this.handleSubmit}>
<label>Name</label>
<input type="text" />
<button type="submit">Submit</button>
</form>
</div>
);
}
}
Conclusion
We've seen in this guide that React events are very similar to JavaScript events, with a few differences in syntax and propagation behavior. We also learned the distinction between event handlers used in functional and class components, with the class component requiring the binding of the handlers to this
. There are many more events that can be handled in React, but they all function in the same way as the onClick
method, whether in a functional or a class component.