Runnable lesson · press Try it on the examples to edit and run them here.
Events are how users talk to your app: clicks, typing, hovering, submitting forms. React lets you attach handlers right in the JSX, with props that start with on.
Attaching a handler
function App() {
const [message, setMessage] = React.useState("Not clicked yet");
function handleClick() {
setMessage("Clicked!");
}
return (
<div>
<button onClick={handleClick}>Click me</button>
<p>{message}</p>
</div>
);
}
onClick is the prop; its value is a function. React calls the function when the button is clicked. Compare it with plain HTML (onclick="handleClick()", a string) and plain JavaScript (addEventListener). In React you never use addEventListener for ordinary elements, and you never need to remove listeners.
Three ways to write the handler
// 1. A named function (best for anything longer than one line)
<button onClick={handleClick}>
// 2. An inline arrow function (good for short logic or passing arguments)
<button onClick={() => setCount(count + 1)}>
// 3. An arrow function that calls the handler with arguments
<button onClick={() => handleDelete(item.id)}>
Never call the function in the attribute: onClick={handleClick()} runs it during rendering. Pass the function itself.
Passing arguments
function App() {
const [fruit, setFruit] = React.useState(null);
const fruits = ["Apple", "Mango", "Pear"];
return (
<div>
<p>{fruit ? `You picked ${fruit}` : "Pick a fruit"}</p>
{fruits.map((f) => (
<button key={f} onClick={() => setFruit(f)}>{f}</button>
))}
</div>
);
}
The event object
React gives your handler an event object as its first argument. It describes what happened:
function App() {
const [info, setInfo] = React.useState("Move the mouse");
return (
<div>
<button onClick={(event) => setInfo("Clicked " + event.target.tagName.toLowerCase() + ", type: " + event.type)}>
Show details
</button>
<p>{info}</p>
</div>
);
}
The Event Object shows the useful properties, preventDefault and stopPropagation.
Common events
| Prop | Fires when |
|---|---|
onClick | The element is clicked (also with the keyboard on buttons) |
onChange | An input’s value changes (on every keystroke, unlike plain DOM) |
onSubmit | A form is submitted |
onKeyDown, onKeyUp | A key is pressed or released |
onFocus, onBlur | An element gets or loses focus |
onMouseEnter, onMouseLeave | The pointer enters or leaves |
onScroll, onWheel | Scrolling |
onDrag..., onTouch..., onPointer... | Dragging, touch and pointer input |
React events are wrapped
The object you receive is a SyntheticEvent, a wrapper that behaves the same in every browser. It has the same methods as the native event, and event.nativeEvent gives you the original. React attaches one listener per event type at the root of your app and works out which handler to call, which is called event delegation (see Event Delegation).
Use the right element
Handlers on elements that are not interactive hurt accessibility. A <div onClick> cannot be reached with the keyboard and is not announced as a button. Use <button> for actions and <a href> for navigation; they come with keyboard support for free.
// Not accessible
<div onClick={save}>Save</div>
// Accessible
<button type="button" onClick={save}>Save</button>
Common mistakes
- Calling instead of passing:
onClick={save()}. - A string handler (
onClick="save()"): that is HTML, not JSX. - Wrong casing:
onclick,onclick; it isonClick. - Forgetting
type="button"on a button inside a form: it defaults tosubmitand reloads the page when clicked.
Key points
- Attach handlers with
onEvent={function}and pass the function itself. - Use an inline arrow function to pass arguments.
- Handlers receive a cross-browser event object; use semantic elements.