Get Started with Modern React: Step by Step
S02・V11: Handling Events
- We will show the difference between handling DOM events in HTML, and handling events with React elements.
- We will show how to prevent default browser behavior in React.
- We will provide an example to show you how to create an event handler in React, and how to specify an extra parameter for it.
Handling Events
Handling events with React elements is very similar to handling events on DOM elements in HTML. However, there are some syntactic differences. Firstly, React events are named using camel-case, rather than lower-case. Secondly, with JSX you pass a function as the event handler, rather than a string.
Button
An example of a button expressed in HTML is:
// HTML Syntax
<button onclick="activateLasers()">Activate Lasers</button>
// `onclick` is lower-case, passed function is `"activateLasers()"`
Note that the onclick
attribute is spelled using lower-case, and the value passed to it is a function call as a string: "activateLasers()"
.
Now, the same button expressed in React JSX syntax would be:
// React JSX Syntax
<button onClick={activateLasers}>Activate Lasers</button>
// `onClick` is camel-case, passed function is `{activateLasers}`
Note that the onClick
prop is spelled using camel-case, and the value passed to it is a reference to a function, within a JSX container: {activateLasers}
.
Please take a note of the differences between HTML and JSX syntax conventions.
Default Browser Behavior
Now, when clicking a link, the default browser behavior is to open a new page.
To prevent this default behavior in HTML, we can return false;
within the string passed to the onclick
attribute.
// HTML Syntax
<a href="" onclick="console.log('Link clicked'); return false">Click me</a>
In React, we would need to call preventDefault()
on the event
to avoid a new page from loading.
// React JSX Syntax
<a href="" onClick={event => {
event.preventDefault();
console.log('Link clicked');
}}>
Click me
</a>
Here, event
is a “synthetic event” created by React. React defines these synthetic events according to the W3C spec, so you don’t need to worry about cross-browser compatibility. When using React you should generally not need to call addEventListener
to add listeners to a DOM element after it is created. Instead, just provide a listener when the element is initially rendered.
Event Handler
A common pattern is for an event handler to be a function within your component.
For example, let’s say we have a Toggle
component which renders a button that lets the user toggle between “ON” and “OFF” states. Inside Toggle
, we will first add the isToggleOn
state to true
initially. We will now name the state value getter and state setter function in the returned two-element array. Now, we will have the component return a button showing the text “ON” or “OFF” depending on the isToggleOn
state.
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Toggle = () => {
const [isToggleOn, setToggleOn] = useState(true);
return (
<button>
{isToggleOn ? "ON" : "OFF"}
</button>
);
};
ReactDOM.render(<Toggle />, document.getElementById("root"));
The button will need to have an onClick
prop to listen for click events. Let’s pass a reference to an event handler function which we will define inside the component, which is a common pattern in React. Within the handleClick
function, we will toggle the state using setToggleOn(!isToggleOn)
.
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Toggle = () => {
const [isToggleOn, setToggleOn] = useState(true);
const handleClick = event => { setToggleOn(!isToggleOn); };
return (
<button onClick={handleClick}> {isToggleOn ? "ON" : "OFF"}
</button>
);
};
ReactDOM.render(<Toggle />, document.getElementById("root"));
Toggle the button in the browser to test it.
Equivalently, we can write the expression passed to the onClick
prop as follows:
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Toggle = () => {
const [isToggleOn, setToggleOn] = useState(true);
const handleClick = event => {
setToggleOn(!isToggleOn);
};
return (
<button onClick={event => handleClick(event)}> {isToggleOn ? "ON" : "OFF"}
</button>
);
};
ReactDOM.render(<Toggle />, document.getElementById("root"));
Passing Arguments to Event Handlers
Inside a loop, where we render several items, such as the rows of a table, we commonly want to pass an extra parameter to an event handler, to be able to identify each item.
For example, let’s say our app renders 5 Toggle
s. We will map over an array with 5 elements to achieve this.
const App = () => ( <div> {[1, 2, 3, 4, 5].map(row => ( <div key={row}> <Toggle /> </div> ))} </div>);
ReactDOM.render(<App />, document.getElementById("root"));
We will pass the row
number to the Toggle
as a prop. We can now make use of the row
number in the Toggle
component, via props
. We can pass the row
number as the first argument to the event click handler. We will need to update the function signature of our handleClick
function, with the row
as the first parameter. Now, we can print out which row was clicked.
import React, { useState } from "react";
import ReactDOM from "react-dom";
const Toggle = props => {
const [isToggleOn, setToggleOn] = useState(true);
const handleClick = (row, event) => { console.log(`Row #${row} was clicked`); setToggleOn(!isToggleOn);
};
return (
<button onClick={event => handleClick(props.row, event)}> {isToggleOn ? "ON" : "OFF"}
</button>
);
};
const App = () => (
<div>
{[1, 2, 3, 4, 5].map(row => (
<div key={row}>
<Toggle row={row} /> </div>
))}
</div>
);
ReactDOM.render(<App />, document.getElementById("root"));
Save the file, and test the app in the browser, using the JavaScript Console.
Summary
We showed the difference between handling DOM events in HTML, and handling events with React elements. We showed how to prevent default browser behavior in React. And, we provided an example to show you how to create an event handler in React, and how to specify an extra parameter for it.
Next Up…
In the next video, we will render elements based on certain conditions.