React Event Handlers
Event handlers let you respond to user actions like clicks, key presses, form input, and mouse movement. React events work similarly to native browser events, with a few differences.
How React events work
React wraps native browser events in its own SyntheticEvent object. This normalizes behaviour across different browsers so you do not have to worry about inconsistencies.
Event names in React are camelCase, not lowercase:
- HTML:
onclick - React:
onClick
You pass a function reference (not a string) as the event handler:
// HTML (do not do this in React):
<button onclick="handleClick()">Click</button>
// React (correct):
<button onClick={handleClick}>Click</button>
Adding event handlers
The most straightforward way is to define a function and pass it to the event prop:
function App() {
function handleClick() {
console.log('Button clicked');
}
return <button onClick={handleClick}>Click me</button>;
}
You can also use an inline arrow function:
function App() {
return (
<button onClick={() => console.log('Button clicked')}>
Click me
</button>
);
}
Both work. Named functions are easier to test and reuse. Inline arrows are convenient for short handlers or when you need to pass arguments.
The event object
React passes the event object automatically to your handler. You can access it to read input values, prevent default behaviour, and more:
function SearchBar() {
function handleChange(event) {
console.log(event.target.value);
}
return <input type="text" onChange={handleChange} />;
}
Preventing default behaviour
Many browser events have a default action: clicking a link navigates, submitting a form reloads the page. Call event.preventDefault() to stop that:
function ContactForm() {
function handleSubmit(event) {
event.preventDefault();
// now handle the submission yourself
console.log('Form submitted');
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
);
}
Passing arguments to event handlers
If you need to pass extra data to a handler, wrap it in an arrow function:
function ItemList({ items }) {
function handleDelete(id) {
console.log('Deleting item', id);
}
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item.name}
<button onClick={() => handleDelete(item.id)}>Delete</button>
</li>
))}
</ul>
);
}
The arrow function () => handleDelete(item.id) creates a new function that, when called, invokes handleDelete with the specific id.
Practical examples
onClick
function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
onChange (input)
function TextInput() {
const [value, setValue] = React.useState('');
return (
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Type something..."
/>
);
}
onSubmit (form)
function LoginForm() {
const [email, setEmail] = React.useState('');
function handleSubmit(e) {
e.preventDefault();
console.log('Submitted:', email);
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<button type="submit">Log in</button>
</form>
);
}
onKeyDown (keyboard)
Use onKeyDown to detect key presses. Note: onKeyPress is deprecated and should not be used in new code.
function SearchInput() {
function handleKeyDown(event) {
if (event.key === 'Enter') {
console.log('Search triggered');
}
if (event.key === 'Escape') {
console.log('Search cancelled');
}
}
return <input type="text" onKeyDown={handleKeyDown} />;
}
onMouseEnter / onMouseLeave (hover)
function HoverCard() {
const [hovered, setHovered] = React.useState(false);
return (
<div
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
style={{ background: hovered ? '#f0f8ff' : '#fff', padding: 16 }}
>
{hovered ? 'You are hovering!' : 'Hover over me'}
</div>
);
}
Supported events
React supports all standard DOM events. Here is a reference:
- Clipboard:
onCopyonCutonPaste - Composition:
onCompositionEndonCompositionStartonCompositionUpdate - Keyboard:
onKeyDownonKeyUp(onKeyPressis deprecated, useonKeyDown) - Focus:
onFocusonBlur - Form:
onChangeonInputonInvalidonResetonSubmit - Generic:
onErroronLoad - Mouse:
onClickonContextMenuonDoubleClickonDragonDragEndonDragEnteronDragLeaveonDragOveronDragStartonDroponMouseDownonMouseEnteronMouseLeaveonMouseMoveonMouseOutonMouseOveronMouseUp - Pointer:
onPointerDownonPointerMoveonPointerUponPointerCancelonGotPointerCaptureonLostPointerCaptureonPointerEnteronPointerLeaveonPointerOveronPointerOut - Selection:
onSelect - Touch:
onTouchCancelonTouchEndonTouchMoveonTouchStart - UI:
onScroll - Wheel:
onWheel - Media:
onAbortonCanPlayonCanPlayThroughonDurationChangeonEmptiedonEncryptedonEndedonErroronLoadedDataonLoadedMetadataonLoadStartonPauseonPlayonPlayingonProgressonRateChangeonSeekedonSeekingonStalledonSuspendonTimeUpdateonVolumeChangeonWaiting - Image:
onLoadonError - Animation:
onAnimationStartonAnimationEndonAnimationIteration - Transition:
onTransitionEnd - Other:
onToggle
For the full event reference, see the React DOM events documentation .
Common mistakes
Calling the function instead of passing it.
// Wrong: handleClick() is called immediately when the component renders
<button onClick={handleClick()}>Click</button>
// Correct: pass a reference, React calls it when the button is clicked
<button onClick={handleClick}>Click</button>
If your handler needs arguments, use an arrow function to wrap it:
<button onClick={() => handleDelete(item.id)}>Delete</button>
Using onKeyPress.
onKeyPress is deprecated. Use onKeyDown instead. onKeyDown fires on every key press including modifier keys, while the now-removed onKeyPress only fired for printable characters.
What to learn next
- React Forms : controlled components, form state, and form submission
- Functional Components : how components receive and use event handlers as props