Handling Events
Events let React components respond to user actions.
React event handlers are passed as functions through JSX props.
function SaveButton() {
function handleClick() {
console.log("Saved");
}
return <button onClick={handleClick}>Save</button>;
}Event Prop Names
React event props use camelCase.
<button onClick={handleClick}>Click</button>
<input onChange={handleChange} />
<form onSubmit={handleSubmit}>...</form>The value should be a function, not a string.
// Bad
<button onclick="save()">Save</button>
// Good
<button onClick={save}>Save</button>Passing Arguments
If a handler needs arguments, wrap it in another function.
function TodoItem({ todo, onToggle }) {
return (
<button onClick={() => onToggle(todo.id)}>
{todo.completed ? "Undo" : "Complete"}
</button>
);
}Do not call the handler during render.
// Wrong: runs immediately
<button onClick={onToggle(todo.id)}>Toggle</button>The Event Object
React passes an event object to handlers.
function SearchBox() {
const [query, setQuery] = useState("");
function handleChange(event) {
setQuery(event.target.value);
}
return <input value={query} onChange={handleChange} />;
}For form fields, event.target.value is the current input value.
For checkboxes, use event.target.checked.
function TermsCheckbox() {
const [accepted, setAccepted] = useState(false);
return (
<label>
<input
type="checkbox"
checked={accepted}
onChange={(event) => setAccepted(event.target.checked)}
/>
I accept the terms
</label>
);
}Preventing Default Behavior
Forms reload the page by default. In React apps, you often prevent that and handle submission in JavaScript.
function SignupForm() {
const [email, setEmail] = useState("");
function handleSubmit(event) {
event.preventDefault();
console.log("Submit", email);
}
return (
<form onSubmit={handleSubmit}>
<input
value={email}
onChange={(event) => setEmail(event.target.value)}
/>
<button type="submit">Sign up</button>
</form>
);
}Set button types intentionally. A plain <button> inside a form submits the form by default.
<button type="button" onClick={openPreview}>
Preview
</button>Event Bubbling
Events bubble from child elements to parent elements.
function Card() {
function handleCardClick() {
console.log("card");
}
function handleButtonClick(event) {
event.stopPropagation();
console.log("button");
}
return (
<article onClick={handleCardClick}>
<h2>Project</h2>
<button onClick={handleButtonClick}>Open menu</button>
</article>
);
}Use stopPropagation sparingly. Often, simpler markup or more specific handlers are better.
Common Mistakes
- Writing
onClick={save()}instead ofonClick={save}. - Forgetting
event.preventDefault()for handled form submissions. - Reading
event.target.valuefrom checkboxes instead ofevent.target.checked. - Using a submit button for an in-form action that should not submit.
- Stopping propagation when the real issue is unclear component structure.
What should you pass to onClick?
Practice Challenge
Build a SearchForm component.
Requirements:
- controlled text input
- submit button
- prevents the browser's default form submission
- calls
onSearch(query)when submitted - includes a clear button with
type="button"
Recap
React events are functions passed through camelCase props. Use event objects for input values, prevent default form behavior when needed, and pass arguments with wrapper functions.