Skip to main content

5.2 - Responding to Events

https://react.dev/learn/responding-to-events

React lets you add event handlers to your JSX. Event handlers are your own functions that will be triggered in response to interactions like clicking, hovering, focusing form inputs, and so on. Event handlers will also catch events from any children your component might have.


Adding event handlers

To add an event handler, you will first define a function and then pass it as a prop to the appropriate JSX tag. For example, here is a button that doesn’t do anything yet:

export default function Button() {
return (
<button>
I don't do anything
</button>
);
}

You can make it show a message when a user clicks by following these three steps:

  1. Declare a function called handleClick inside your Button component.
  2. Implement the logic inside that function (use alert to show the message).
  3. Add onClick={handleClick} to the <button> JSX.
export default function Button() {
function handleClick() {
alert('You clicked me!');
}

return (
<button onClick={handleClick}>
Click me
</button>
);
}

You defined the handleClick function and then passed it as a prop to <button>. handleClick is an event handler.

Event handler functions:

  • Are usually defined inside your components.
  • Have names that start with handle, followed by the name of the event.
    • You’ll often see onClick={handleClick}, onMouseEnter={handleMouseEnter}, and so on.

Alternatively, you can more concisely define an event handler with arrow function in the JSX, which is convenient for short functions:

<button onClick={() => {
alert('You clicked me!');
}}>
warning

Functions Passed to Event Handlers Must Be Passed, Not Called

For example:

passing a function (correct)calling a function (incorrect)
<button onClick={handleClick}><button onClick={handleClick()}>

In the first example, the handleClick function is passed as an onClick event handler. This tells React to remember it and only call your function when the user clicks the button.

In the second example, the () at the end of handleClick() fires the function immediately during rendering, without any clicks. This is because JavaScript inside the JSX { } executes right away.

When you write code inline, the same pitfall presents itself in a different way:

passing a function (correct)calling a function (incorrect)
<button onClick={() => alert('...')}><button onClick={alert('...')}>

In both cases, what you want to pass is a function:

<button onClick={handleClick}> passes the handleClick function.
<button onClick={() => alert('...')}> passes the () => alert('...') function.

Reading props in event handlers

Because event handlers are declared inside of a component, they have access to the component’s props. Here is a button that, when clicked, shows an alert with its message prop:

function AlertButton({ message, children }) {
return (
<button onClick={() => alert(message)}>
{children}
</button>
);
}

export default function Toolbar() {
return (
<div>
<AlertButton message="Playing!">
Play Movie
</AlertButton>
<AlertButton message="Uploading!">
Upload Image
</AlertButton>
</div>
);
}

This lets these two buttons show different messages.


Passing event handlers as props

Often you’ll want the parent component to specify a child’s event handler.

Consider buttons: depending on where you’re using a Button component, you might want to execute a different function—perhaps one plays a movie and another uploads an image.

To do this, pass a prop the component receives from its parent as the event handler like so:

function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}

function PlayButton({ movieName }) {
function handlePlayClick() {
alert(`Playing ${movieName}!`);
}

return (
<Button onClick={handlePlayClick}>
Play "{movieName}"
</Button>
);
}

export default function Toolbar() {
return (
<div>
<PlayButton movieName="Kiki's Delivery Service" />
</div>
);
}

Here, the Toolbar component renders a PlayButton :

PlayButton passes handlePlayClick as the onClick prop to the Button inside.

Finally, your Button component accepts a prop called onClick. It passes that prop directly to the built-in browser <button> with onClick={onClick}. This tells React to call the passed function on click.

note

Make sure that you use the appropriate HTML tags for your event handlers. For example, to handle clicks, use <button onClick={handleClick}> instead of <div onClick={handleClick}>. Using a real browser <button> enables built-in browser behaviors like keyboard navigation.


Preventing default behavior

Some browser events have default behavior associated with them. For example, a <form> submit event, which happens when a button inside of it is clicked, will reload the whole page by default.

You can call e.preventDefault() on the event object to stop this from happening:


export default function Signup() {
return (
<form onSubmit={e => {
// prevents default behavior of the page reloading onSubmit
e.preventDefault();
alert('Submitting!');
}}>
<input />
<button>Send</button>
</form>
);
}

Can event handlers have side effects? Absolutely! Event handlers are the best place for side effects.

Unlike rendering functions, event handlers don’t need to be pure, so it’s a great place to change something—for example, change an input’s value in response to typing, or change a list in response to a button press.

However, in order to change some information, you first need some way to store it. In React, this is done by using state, a component’s memory. You will learn all about it on the next page.