Handling Events in React – Making UI Respond to Users
A web application isn't useful if it only displays information.
Users need to:
Click buttons
Type into inputs
Submit forms
Hover over elements
Select options
Press keyboard keys
Interact with different parts of the UI
React provides a clean way to handle these interactions using Event Handlers.
On Day 63, I learned that State makes React components interactive.
Today, I'm learning how Events trigger those state changes.
The basic flow is:
User Interaction
↓
Event Handler
↓
State Update
↓
Component Re-renders
↓
Updated UI
🧠 What Are Events?
An event is something that happens because of an interaction or browser activity.
For example:
Click
Typing
Submit
Mouse Enter
Mouse Leave
Key Press
Change
Focus
Blur
In normal JavaScript, we might write:
button.addEventListener("click", handleClick);
In React, we generally write:
<button onClick={handleClick}>
Click Me
</button>
React uses event props such as:
onClick
onChange
onSubmit
onMouseEnter
onMouseLeave
onFocus
onBlur
onKeyDown
onKeyUp
⚛️ React Event Naming
One important difference from HTML is camelCase.
HTML:
<button onclick="handleClick()">
React:
<button onClick={handleClick}>
Examples:
onClick
onChange
onSubmit
onMouseEnter
onMouseLeave
React event names are typically written in camelCase.
🖱️ onClick
The most commonly used React event is:
onClick
Example:
function App() {
function handleClick() {
console.log("Button clicked!");
}
return (
<button onClick={handleClick}>
Click Me
</button>
);
}
When the user clicks the button:
Click
↓
handleClick()
↓
"Button clicked!"
⚠️ Don't Call the Function During Rendering
This is a very important React concept.
❌ Incorrect
<button onClick={handleClick()}>
Click
</button>
This executes the function while React is rendering.
✅ Correct
<button onClick={handleClick}>
Click
</button>
Here, we're giving React the function to execute when the click occurs.
⚡ Inline Event Handlers
We can also write the function directly:
<button onClick={() => console.log("Clicked!")}>
Click Me
</button>
This is useful for small actions.
For example:
<button onClick={() => alert("Hello!")}>
Say Hello
</button>
🔥 Events + State
This is where today's lesson connects directly to Day 63.
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
function increase() {
setCount(prev => prev + 1);
}
return (
<div>
<h2>{count}</h2>
<button onClick={increase}>
Increase
</button>
</div>
);
}
The complete flow is:
User clicks button
↓
onClick
↓
increase()
↓
setCount()
↓
State changes
↓
React re-renders
↓
New count displayed
This pattern appears everywhere in React.
📝 Handling Input Changes
One of the most important events for forms is:
onChange
Example:
function App() {
function handleChange(event) {
console.log(event.target.value);
}
return (
<input
type="text"
onChange={handleChange}
/>
);
}
Every time the user types, handleChange runs.
🎯 Understanding the Event Object
React passes an event object to the handler.
function handleChange(event) {
console.log(event);
}
For an input:
event.target
represents the input element.
And:
event.target.value
gives us its current value.
For example, if the user types:
Saurabh
then:
event.target.value
will contain:
"Saurabh"
⚛️ Controlled Inputs
React applications commonly use controlled components.
Example:
import { useState } from "react";
function App() {
const [name, setName] = useState("");
function handleChange(event) {
setName(event.target.value);
}
return (
<div>
<input
value={name}
onChange={handleChange}
/>
<p>Hello, {name}</p>
</div>
);
}
Here the flow is:
User types
↓
onChange
↓
event.target.value
↓
setName()
↓
State updates
↓
Input + UI update
The state is controlling the input.
That's why it's called a controlled input.
🧠 Why Controlled Inputs Matter
Controlled inputs give React a reliable source of truth.
Instead of the input independently managing its value:
Input
we have:
React State
↓
Input
↓
User types
↓
onChange
↓
React State
This becomes extremely useful when building:
Login forms
Registration forms
Search bars
Filters
Checkout forms
Profile editors
📤 Handling Form Submission
React forms use:
onSubmit
Example:
function LoginForm() {
function handleSubmit(event) {
event.preventDefault();
console.log("Form submitted");
}
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<button type="submit">
Login
</button>
</form>
);
}
🛑 What Does preventDefault() Do?
Normally, submitting an HTML form can trigger the browser's default form behavior.
In React applications, we often want to handle the submission ourselves.
So:
event.preventDefault();
prevents the browser's default behavior.
Then we can:
Read form data
↓
Validate data
↓
Send API request
↓
Display result
🧩 Complete Form Example
import { useState } from "react";
function LoginForm() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
function handleSubmit(event) {
event.preventDefault();
console.log({
email,
password
});
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={event => setEmail(event.target.value)}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={event => setPassword(event.target.value)}
placeholder="Password"
/>
<button type="submit">
Login
</button>
</form>
);
}
Now React controls both inputs and the form submission.
🖱️ Mouse Events
React supports several mouse events.
onMouseEnter
<div onMouseEnter={handleMouseEnter}>
Hover over me
</div>
onMouseLeave
<div onMouseLeave={handleMouseLeave}>
Leave me
</div>
onMouseDown
<button onMouseDown={handleMouseDown}>
Press
</button>
onMouseUp
<button onMouseUp={handleMouseUp}>
Release
</button>
These can be useful for interactive UI components.
⌨️ Keyboard Events
React also allows us to respond to keyboard interactions.
onKeyDown
<input
onKeyDown={event => {
console.log(event.key);
}}
/>
If the user presses:
Enter
then:
event.key
will be:
"Enter"
🚀 Example: Detect Enter
function Search() {
function handleKeyDown(event) {
if (event.key === "Enter") {
console.log("Search triggered");
}
}
return (
<input
placeholder="Search..."
onKeyDown={handleKeyDown}
/>
);
}
This is commonly used for:
Search boxes
Chat applications
Command interfaces
Keyboard shortcuts
🎯 Passing Arguments to Event Handlers
Suppose we have:
function greet(name) {
console.log(`Hello ${name}`);
}
We shouldn't write:
❌ onClick={greet("Saurabh")}
Instead:
<button onClick={() => greet("Saurabh")}>
Greet
</button>
The arrow function delays execution until the click.
📦 Event Handler With Multiple Arguments
function handleUser(id, name) {
console.log(id, name);
}
Then:
<button
onClick={() => handleUser(101, "Saurabh")}
>
Select User
</button>
This pattern is very useful when rendering lists.
🔄 Events and Props
Event handlers can also be passed through props.
Parent:
function App() {
function handleClick() {
console.log("Clicked!");
}
return <Button onClick={handleClick} />;
}
Child:
function Button({ onClick }) {
return (
<button onClick={onClick}>
Click Me
</button>
);
}
The flow is:
Parent
│
│ passes function
↓
Child
│
│ user clicks
↓
Event Handler
│
↓
Parent function runs
This is an important concept because it allows child components to communicate user interactions back to the parent.
🔥 Example: Child Button Updating Parent State
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
function increaseCount() {
setCount(prev => prev + 1);
}
return (
<div>
<h2>{count}</h2>
<CounterButton onIncrease={increaseCount} />
</div>
);
}
function CounterButton({ onIncrease }) {
return (
<button onClick={onIncrease}>
Increase
</button>
);
}
export default App;
Notice what's happening.
The child doesn't directly modify the parent's state.
Instead:
Child
↓
calls function received through props
↓
Parent updates state
↓
Parent re-renders
This follows React's one-way data flow.
🧠 Event Bubbling
Events can also propagate from a child element toward its ancestors.
Consider:
<div onClick={() => console.log("Parent")}>
<button onClick={() => console.log("Button")}>
Click
</button>
</div>
Clicking the button can result in:
Button
↓
Parent
The event bubbles upward.
So you might see:
Button
Parent
in the console.
This concept becomes especially important when we later learn Event Delegation and more advanced interaction patterns.
🛑 Stopping Event Propagation
We can stop an event from continuing upward using:
event.stopPropagation();
Example:
function handleButtonClick(event) {
event.stopPropagation();
console.log("Button clicked");
}
Then:
<div onClick={() => console.log("Parent")}>
<button onClick={handleButtonClick}>
Click
</button>
</div>
The button's event won't continue to the parent handler.
🧠 React Event Handling vs DOM Event Handling
You may notice that React feels similar to vanilla JavaScript.
Vanilla JS:
button.addEventListener("click", handleClick);
React:
<button onClick={handleClick}>
The major difference is that React lets us express the event handling directly as part of the component's UI declaration.
🏆 Best Practices
1. Use descriptive handler names
Prefer:
handleSubmit
handleLogin
handleSearch
handleDelete
handleToggle
instead of:
fn1
abc
click
2. Keep event handlers focused
Instead of putting huge amounts of logic inside JSX:
<button
onClick={() => {
// 30 lines of logic
}}
>
prefer:
function handleClick() {
// logic
}
Then:
<button onClick={handleClick}>
3. Use functional updates when updating from previous state
setCount(prev => prev + 1);
4. Use preventDefault() when you need custom form behavior
function handleSubmit(event) {
event.preventDefault();
}
5. Pass functions, don't execute them
✅
onClick={handleClick}
❌
onClick={handleClick()}
6. Use state for UI-driven changes
Events become especially powerful when connected to state.
Event
↓
Handler
↓
State
↓
UI
🧪 A Complete Interactive Example
Let's combine today's concepts.
import { useState } from "react";
function App() {
const [name, setName] = useState("");
const [submittedName, setSubmittedName] = useState("");
function handleSubmit(event) {
event.preventDefault();
setSubmittedName(name);
}
return (
<div>
<h1>Welcome</h1>
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={event => setName(event.target.value)}
placeholder="Enter your name"
/>
<button type="submit">
Submit
</button>
</form>
{submittedName && (
<p>
Hello, {submittedName}! 👋
</p>
)}
</div>
);
}
export default App;
This tiny application uses:
State
useStateonChangeonSubmitEvent object
preventDefault()Controlled input
Conditional rendering
And that's already starting to look like a real application.
💡 My Biggest Takeaway
Today's biggest takeaway is:
Events are the bridge between the user and React State.
State stores the data.
Events detect what the user does.
Event handlers decide what should happen.
React then updates the UI.
The complete mental model is:
User
↓
Interaction
↓
React Event
↓
Event Handler
↓
State Update
↓
Re-render
↓
Updated UI
Once this pattern becomes natural, building interactive React applications becomes much easier.
🚀 Final Summary
Today I learned:
What events are
React event handlers
onClickonChangeonSubmitMouse events
Keyboard events
Event objects
event.targetevent.target.valueControlled inputs
preventDefault()Passing arguments to handlers
Passing event handlers through props
Parent-child event communication
Event bubbling
stopPropagation()Event handling best practices
Yesterday:
State → stores changing data
Today:
Events → respond to user interactions
Together:
User Interaction
↓
Event
↓
Event Handler
↓
State
↓
Re-render
↓
Updated UI
That's the foundation of interactive React applications. ⚛️🚀
