Event Handling
React events look like HTML attributes, but you pass functions instead of strings. Clicks, typing, form submits — all handled with the same simple pattern.
On this page · 5 min · Beginner
On this page
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Beginner
- Updated
- Oct 28, 2026
Related tutorials
Learning objectives#
- Attach handlers with onClick, onChange and onSubmit
- Pass arguments to handlers correctly
- Use the event object and preventDefault
- Name and pass handlers between components
Explanation#
Events use camelCase props with a function: <button onClick={handleClick}>. Pass the function itself — do not call it.
To pass arguments, wrap in an arrow: onClick={() => remove(item.id)}.
The handler receives a synthetic event with the familiar API: e.target.value, e.preventDefault(), e.stopPropagation(), e.key for keyboard events.
Forms: handle onSubmit on the <form> and call e.preventDefault() so the page does not reload.
Conventions: handler functions are named handleSomething; props that accept handlers are named onSomething (onSave={handleSave}).
Syntax#
<button onClick={handleSave}>Save</button>
<button onClick={() => remove(id)}>Delete</button>
<input onChange={e => setName(e.target.value)} />
<form onSubmit={e => { e.preventDefault(); send(); }}>
Code example: Clicks, keys and a form#
import { useState } from 'react';
export default function Events() {
const [log, setLog] = useState([]);
const [name, setName] = useState('');
const add = message => setLog(prev => [message, ...prev].slice(0, 5));
function handleSubmit(e) {
e.preventDefault(); // no page reload
add(`Submitted: ${name || '(empty)'}`);
setName('');
}
function handleKeyDown(e) {
if (e.key === 'Escape') {
setName('');
add('Cleared with Escape');
}
}
return (
<>
{['Pen', 'Notebook'].map(item => (
<button key={item} onClick={() => add(`Clicked ${item}`)}>{item}</button>
))}
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={e => setName(e.target.value)}
onKeyDown={handleKeyDown}
aria-label="Your name"
/>
<button type="submit">Send</button>
</form>
<ol>{log.map((line, i) => <li key={i}>{line}</li>)}</ol>
</>
);
}
Clicking “Pen” adds “Clicked Pen” to the log. Typing a name and pressing Enter or Send adds “Submitted: Asha” without reloading the page. Pressing Escape in the input clears it and logs “Cleared with Escape”. The log keeps the latest five lines.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- Each item button uses an arrow function to pass its own name to add.
- onChange keeps the input in sync with the name state.
- onKeyDown checks e.key to react to Escape.
- handleSubmit runs for both Enter and the Send button and prevents the page reload.
Real-world use case#
A chat input sends on Enter, adds a newline on Shift+Enter, and clears on Escape — all from one onKeyDown handler reading e.key and e.shiftKey.
Common mistakes#
This calls the function during render (and may loop forever if it sets state). Pass handleClick or () => handleClick(x).
Without it the browser submits the form and reloads the page, losing your state.
Divs are not focusable or keyboard-accessible. Use <button>.
Best practices#
- Name handlers handleX and props onX
- Use buttons for actions
- Handle forms with onSubmit
- Keep handlers short; move logic into functions
Remember this#
Pass the function, do not call it.
Arguments? Wrap: () => fn(arg).
Forms: onSubmit + e.preventDefault().
Practice exercise#
Your task: Build a LikeButton that shows "♡ Like" and becomes "♥ Liked" when clicked, toggling back on the next click.
Need a hint?
Show solution
import { useState } from 'react';
export default function LikeButton() {
const [liked, setLiked] = useState(false);
return (
<button onClick={() => setLiked(l => !l)} aria-pressed={liked}>
{liked ? '♥ Liked' : '♡ Like'}
</button>
);
}
Mini quiz#
What is wrong here?
<button onClick={deleteItem(5)}>Delete</button>
Want more? Practise all React MCQs · React interview questions
My notes#
Saved in this browser.