What Are Events in React?
Imagine you're a doorbell system in a house:
IMPERATIVE WAY (Vanilla JavaScript - Old School):
┌─────────────────────────────────────────┐
│ OLD DOORBELL SYSTEM │
│ │
│ 1. Find the doorbell button │
│ document.querySelector('.bell') │
│ │
│ 2. Attach listener manually │
│ button.addEventListener('click', │
│ function() { ringBell() }) │
│ │
│ 3. Later, remove it manually │
│ button.removeEventListener(...) │
│ │
│ Problem: You manually wire everything! │
│ Like an electrician crawling in walls. │
│ │
│ In JavaScript: │
│ const btn = document.querySelector('button');│
│ btn.addEventListener('click', handleClick); │
└─────────────────────────────────────────┘
DECLARATIVE WAY (React - Modern):
┌─────────────────────────────────────────┐
│ SMART DOORBELL SYSTEM │
│ │
│ Just declare what should happen: │
│ │
│ <button onClick={ringBell}> │
│ Ring Bell │
│ </button> │
│ │
│ React handles the wiring automatically!│
│ Like a smart home - just say what you │
│ want, the system does the rest. │
│ │
│ No manual DOM selection! │
│ No manual listener attachment! │
│ Just declare the event on the element! │
│ │
│ In React: │
│ <button onClick={handleClick}>Click</button> │
└─────────────────────────────────────────┘
KEY INSIGHT:
Imperative = "Tell HOW to do it step by step"
Declarative = "Say WHAT you want, let React handle HOW"
The Big Problem: "Function vs Function Call"
// ==========================================
// THE "IMMEDIATE EXECUTION" TRAP
// ==========================================
// WRONG: Calling the function immediately!
function App() {
return (
<button onClick={alert("TEST")}>
Click me
</button>
);
}
// What happens:
// 1. React renders the component
// 2. Sees alert("TEST") - EXECUTES IT IMMEDIATELY!
// 3. Alert shows BEFORE you click!
// 4. onClick gets the RETURN VALUE of alert (undefined)
// 5. When you click, nothing happens (undefined is not a function)
// Visual:
// React renders → sees alert("TEST") → RUNS IT NOW! → Alert pops up! →
// User confused: "I didn't click yet!" → onClick = undefined → Click does nothing
// ==========================================
// THE SOLUTION: Pass the function, don't call it!
// ==========================================
// CORRECT: Pass the function reference
function App() {
return (
<button onClick={() => alert("TEST")}>
Click me
</button>
);
}
// What happens:
// 1. React renders the component
// 2. Sees () => alert("TEST") - Creates a function (doesn't run it!)
// 3. Stores this function as the click handler
// 4. When user clicks, React calls the function
// 5. Alert shows AFTER click!
// Visual:
// React renders → sees () => alert("TEST") → Creates function box →
// Stores for later → User clicks → React opens box → alert("TEST") runs! →
// Alert pops up! → User: "Yay, it worked when I clicked!"
// ==========================================
// EVEN BETTER: Define function separately
// ==========================================
// BEST PRACTICE: Named handler function
function App() {
// Define the handler function
function handleClick() {
alert("TEST");
}
return (
<button onClick={handleClick}> {/* Pass the function reference */}
Click me
</button>
);
}
// Why this is better:
// 1. Clean separation of logic and JSX
// 2. Reusable (can use handleClick in multiple places)
// 3. Easier to read and maintain
// 4. Standard React naming (handle + EventName)
Complete Basic Examples
Create file: react-event-handling.js
// ==========================================
// EVENT HANDLING IN REACT - Complete Guide
// ==========================================
/*
EVENT HANDLING PATTERN:
┌─────────────────────────────────────────┐
│ 1. Define handler function INSIDE component │
│ 2. Name it handle + EventName (convention) │
│ 3. Pass it to onEventName prop (NO CALL!) │
│ 4. React calls it when event happens │
└─────────────────────────────────────────┘
*/
// ==========================================
// EXAMPLE 1: Basic onClick (Inline Arrow Function)
// ==========================================
function App() {
return (
<div>
{/* Inline arrow function - OK for simple cases */}
<button onClick={() => alert("Hello!")}>
Say Hello
</button>
</div>
);
}
// Visual:
// User clicks button → React calls () => alert("Hello!") → Alert shows "Hello!"
// ==========================================
// EXAMPLE 2: Basic onClick (Named Handler - BEST PRACTICE)
// ==========================================
function App() {
// Handler function defined inside component
function handleClick() {
alert("Hello from handler!");
}
return (
<div>
{/* Pass the FUNCTION REFERENCE, don't call it! */}
<button onClick={handleClick}>
Say Hello
</button>
</div>
);
}
// Visual:
// Component renders → handleClick function created →
// Button gets reference to handleClick →
// User clicks → React calls handleClick() → Alert shows!
// ==========================================
// EXAMPLE 3: onClick with Parameters
// ==========================================
function App() {
const step = 1;
// Handler with parameter
function handleStepChange(newStep) {
alert(`Moving to step ${newStep}`);
}
return (
<div>
{/* WRONG: This calls the function immediately! */}
{/* <button onClick={handleStepChange(2)}>Next</button> */}
{/* This would alert immediately on render! */}
{/* CORRECT: Wrap in arrow function */}
<button onClick={() => handleStepChange(step + 1)}>
Next Step
</button>
</div>
);
}
// Why the arrow function wrapper?
// onClick={() => handleStepChange(step + 1)}
// ↑
// Creates a new function that, WHEN CALLED, will run handleStepChange(2)
// React stores this wrapper function
// When clicked, React calls the wrapper → which calls handleStepChange(2)
// ==========================================
// EXAMPLE 4: Multiple Event Types
// ==========================================
function App() {
function handleClick() {
console.log("Button clicked!");
}
function handleMouseEnter() {
console.log("Mouse entered button!");
}
function handleMouseLeave() {
console.log("Mouse left button!");
}
return (
<button
onClick={handleClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
Hover and Click Me!
</button>
);
}
// Event sequence when user interacts:
// 1. Mouse moves over button → handleMouseEnter runs
// 2. User clicks button → handleClick runs
// 3. Mouse leaves button → handleMouseLeave runs
// ==========================================
// EXAMPLE 5: The Steps Component (From Tutorial)
// ==========================================
function App() {
const step = 1;
const messages = [
"Learn React ",
"Apply for jobs ",
"Invest your new income "
];
// Event handler functions
function handlePrevious() {
alert("Previous clicked!");
// Later: setStep(step - 1);
}
function handleNext() {
alert("Next clicked!");
// Later: setStep(step + 1);
}
return (
<div className="steps">
<div className="numbers">
<div className={`${step >= 1 ? "active" : ""}`}>1</div>
<div className={`${step >= 2 ? "active" : ""}`}>2</div>
<div className={`${step >= 3 ? "active" : ""}`}>3</div>
</div>
<p className="message">
Step {step}: {messages[step - 1]}
</p>
<div className="buttons">
<button
style={{ backgroundColor: "#7950f2", color: "#fff" }}
onClick={handlePrevious}
>
Previous
</button>
<button
style={{ backgroundColor: "#7950f2", color: "#fff" }}
onClick={handleNext}
>
Next
</button>
</div>
</div>
);
}
// Visual Flow:
// 1. App component renders
// 2. handlePrevious and handleNext functions are created
// 3. Buttons get references to these functions
// 4. User clicks "Next" → React calls handleNext()
// 5. Alert shows "Next clicked!"
// 6. (Future: will update step state instead of alert)
Interactive React Usage Examples
Complete React File: EventHandlingMasterClass.jsx
import React, { useState } from 'react';
// ==========================================
// INTERACTIVE EVENT HANDLING DEMO
// ==========================================
function EventHandlingMasterClass() {
const [activeDemo, setActiveDemo] = useState('basic');
const demos = {
basic: { title: 'Basic Click', component: <BasicClickDemo /> },
wrong: { title: 'Common Mistakes', component: <MistakesDemo /> },
multiple: { title: 'Multiple Events', component: <MultipleEventsDemo /> },
steps: { title: 'Steps Component', component: <StepsEventDemo /> }
};
return (
<div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<header style={{ background: '#e9c46a', color: '#264653', padding: '30px', borderRadius: '10px', marginBottom: '30px' }}>
<h1 style={{ margin: 0 }}> Event Handling in React</h1>
<p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>onClick, onMouseEnter & The Function Trap</p>
</header>
<nav style={{ display: 'flex', gap: '10px', marginBottom: '30px', flexWrap: 'wrap' }}>
{Object.entries(demos).map(([key, { title }]) => (
<button
key={key}
onClick={() => setActiveDemo(key)}
style={{
padding: '12px 24px',
fontSize: '16px',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
backgroundColor: activeDemo === key ? '#264653' : '#e0e0e0',
color: activeDemo === key ? 'white' : '#333',
fontWeight: activeDemo === key ? 'bold' : 'normal'
}}
>
{title}
</button>
))}
</nav>
<main style={{ background: '#f8f9fa', padding: '30px', borderRadius: '10px', minHeight: '400px' }}>
{demos[activeDemo].component}
</main>
</div>
);
}
// ==========================================
// DEMO 1: Basic Click Handler
// ==========================================
function BasicClickDemo() {
const [clickCount, setClickCount] = useState(0);
function handleClick() {
setClickCount(count => count + 1);
}
return (
<div>
<h2>Basic onClick Handler</h2>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* Method 1: Inline Arrow */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Method 1: Inline Arrow</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`<button onClick={() => alert("Hello!")}>
Click Me
</button>`}
</pre>
<button
onClick={() => alert("Hello!")}
style={{ padding: '10px 20px', background: '#2196f3', color: 'white', border: 'none', borderRadius: '5px' }}
>
Try Me
</button>
<p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
<em>Good for: Simple one-liners</em>
</p>
</div>
{/* Method 2: Named Handler */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Method 2: Named Handler (Preferred)</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`function handleClick() {
setClickCount(c => c + 1);
}
<button onClick={handleClick}>
Clicked {clickCount} times
</button>`}
</pre>
<button
onClick={handleClick}
style={{ padding: '10px 20px', background: '#4caf50', color: 'white', border: 'none', borderRadius: '5px' }}
>
Clicked {clickCount} times
</button>
<p style={{ fontSize: '14px', color: '#666', marginTop: '10px' }}>
<em>Good for: Reusable logic, complex handlers</em>
</p>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 2: Common Mistakes
// ==========================================
function MistakesDemo() {
const [renderCount, setRenderCount] = useState(0);
// This would cause infinite re-renders if used!
// handleWrong() is CALLED immediately
function handleWrong() {
alert("This runs immediately on render!");
}
function handleRight() {
alert("This runs only when you click!");
}
return (
<div>
<h2>Common Mistakes</h2>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* WRONG WAY */}
<div style={{ padding: '20px', background: '#ffebee', borderRadius: '8px' }}>
<h3 style={{ color: '#c62828' }}> WRONG: Calling the function</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`// BAD! This calls the function immediately!
<button onClick={handleWrong()}>
Click Me
</button>`}
</pre>
<p style={{ background: '#ffcdd2', padding: '10px', borderRadius: '4px', fontSize: '14px' }}>
<strong>What happens:</strong><br/>
1. Component renders<br/>
2. React sees handleWrong()<br/>
3. <strong>CALLS IT IMMEDIATELY!</strong><br/>
4. onClick gets the return value (undefined)<br/>
5. Clicking does nothing!
</p>
</div>
{/* RIGHT WAY */}
<div style={{ padding: '20px', background: '#e8f5e9', borderRadius: '8px' }}>
<h3 style={{ color: '#2e7d32' }}> CORRECT: Passing the function</h3>
<pre style={{ background: '#1e1e1e', color: '#d4d4d4', padding: '15px', borderRadius: '4px', fontSize: '13px' }}>
{`// GOOD! Pass the function reference
<button onClick={handleRight}>
Click Me
</button>`}
</pre>
<p style={{ background: '#c8e6c9', padding: '10px', borderRadius: '4px', fontSize: '14px' }}>
<strong>What happens:</strong><br/>
1. Component renders<br/>
2. React sees handleRight<br/>
3. <strong>Stores the function reference</strong><br/>
4. onClick = the function<br/>
5. When clicked, React calls it!
</p>
<button
onClick={handleRight}
style={{ marginTop: '10px', padding: '10px 20px', background: '#4caf50', color: 'white', border: 'none', borderRadius: '5px' }}
>
Try Me (Works!)
</button>
</div>
</div>
<div style={{ marginTop: '20px', padding: '15px', background: '#fff3e0', borderRadius: '8px' }}>
<h4> Memory Trick:</h4>
<p><strong>onClick={handleClick}</strong> → "When clicked, use this function" (PASS)</p>
<p><strong>onClick={handleClick()}</strong> → "Run this function NOW!" (CALL - WRONG!)</p>
</div>
</div>
);
}
// ==========================================
// DEMO 3: Multiple Event Types
// ==========================================
function MultipleEventsDemo() {
const [events, setEvents] = useState([]);
function addEvent(eventName) {
setEvents(prev => [...prev, { name: eventName, time: new Date().toLocaleTimeString() }]);
}
function clearEvents() {
setEvents([]);
}
return (
<div>
<h2>Multiple Event Types</h2>
<div style={{ display: 'grid', gap: '20px', gridTemplateColumns: '1fr 1fr' }}>
{/* Interactive Button */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Interactive Button</h3>
<button
onClick={() => addEvent('Click')}
onMouseEnter={() => addEvent('MouseEnter')}
onMouseLeave={() => addEvent('MouseLeave')}
onFocus={() => addEvent('Focus')}
style={{
padding: '20px 40px',
fontSize: '18px',
backgroundColor: '#7950f2',
color: 'white',
border: 'none',
borderRadius: '8px',
cursor: 'pointer'
}}
>
Interact with me!
</button>
<div style={{ marginTop: '15px', padding: '10px', background: '#f5f5f5', borderRadius: '4px', fontSize: '14px' }}>
<strong>Events on this button:</strong>
<ul style={{ margin: '5px 0', paddingLeft: '20px' }}>
<li>onClick</li>
<li>onMouseEnter</li>
<li>onMouseLeave</li>
<li>onFocus</li>
</ul>
</div>
</div>
{/* Event Log */}
<div style={{ padding: '20px', background: 'white', borderRadius: '8px', border: '2px solid #e0e0e0' }}>
<h3>Event Log</h3>
<button
onClick={clearEvents}
style={{ marginBottom: '10px', padding: '5px 15px', fontSize: '14px' }}
>
Clear Log
</button>
<div style={{ maxHeight: '200px', overflow: 'auto', background: '#1e1e1e', padding: '10px', borderRadius: '4px' }}>
{events.length === 0 ? (
<p style={{ color: '#666', fontStyle: 'italic' }}>No events yet. Try interacting!</p>
) : (
events.map((e, i) => (
<div key={i} style={{ color: '#d4d4d4', fontSize: '13px', marginBottom: '4px' }}>
<span style={{ color: '#4caf50' }}>{e.time}</span> - {e.name}
</div>
))
)}
</div>
</div>
</div>
</div>
);
}
// ==========================================
// DEMO 4: Steps Component with Events
// ==========================================
function StepsEventDemo() {
const [step, setStep] = useState(1);
const [isOpen, setIsOpen] = useState(true);
const messages = [
"Learn React ",
"Apply for jobs ",
"Invest your new income "
];
function handlePrevious() {
if (step > 1) setStep(s => s - 1);
}
function handleNext() {
if (step < 3) setStep(s => s + 1);
}
return (
<div>
<h2>Steps Component with Event Handlers</h2>
<button
onClick={() => setIsOpen(!isOpen)}
style={{ marginBottom: '20px', padding: '10px 20px' }}
>
{isOpen ? 'Close' : 'Open'}
</button>
{isOpen && (
<div style={{
padding: '30px',
background: 'white',
borderRadius: '10px',
boxShadow: '0 2px 10px rgba(0,0,0,0.1)'
}}>
{/* Step Numbers */}
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '30px' }}>
{[1, 2, 3].map(num => (
<div key={num} style={{
width: '40px',
height: '40px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold',
backgroundColor: step >= num ? '#7950f2' : '#e0e0e0',
color: step >= num ? 'white' : '#333'
}}>
{num}
</div>
))}
</div>
{/* Message */}
<p style={{
textAlign: 'center',
fontSize: '20px',
marginBottom: '30px',
padding: '20px',
background: '#f5f5f5',
borderRadius: '8px'
}}>
Step {step}: {messages[step - 1]}
</p>
{/* Buttons */}
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<button
onClick={handlePrevious}
style={{
padding: '10px 20px',
backgroundColor: '#7950f2',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: step > 1 ? 'pointer' : 'not-allowed',
opacity: step > 1 ? 1 : 0.5
}}
>
Previous
</button>
<button
onClick={handleNext}
style={{
padding: '10px 20px',
backgroundColor: '#7950f2',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: step < 3 ? 'pointer' : 'not-allowed',
opacity: step < 3 ? 1 : 0.5
}}
>
Next
</button>
</div>
</div>
)}
</div>
);
}
export default EventHandlingMasterClass;
Memory Aids for Poor Logic Thinking
The "Remote Control" Analogy
┌─────────────────────────────────────────────────┐
│ FUNCTION REFERENCE vs FUNCTION CALL │
│ │
│ = REMOTE CONTROL ANALOGY │
│ │
│ TV = React Component │
│ Remote = Event Handler │
│ │
│ SCENARIO 1: Passing the remote (CORRECT) │
│ ┌─────────────────────────────────────────┐ │
│ │ onClick={handleClick} │ │
│ │ │ │
│ │ Imagine giving someone the remote: │ │
│ │ "Here's the remote. Press power │ │
│ │ when you want to turn on the TV." │ │
│ │ │ │
│ │ They hold the remote, wait, │ │
│ │ then press the button when ready. │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ RESULT: TV turns on when they press! │
│ │
│ SCENARIO 2: Pressing the button yourself (WRONG) │
│ ┌─────────────────────────────────────────┐ │
│ │ onClick={handleClick()} │ │
│ │ │ │
│ │ Imagine pressing the button yourself │ │
│ │ and THEN handing them the remote: │ │
│ │ "I already pressed power. Here's │ │
│ │ the remote." │ │
│ │ │ │
│ │ TV turns on immediately! │ │
│ │ The remote button does nothing now. │ │
│ └─────────────────────────────────────────┘ │
│ ↓ │
│ RESULT: TV turns on immediately, not on click! │
│ │
│ KEY RULE: │
│ {handleClick} = "Here's the remote" (PASS) │
│ {handleClick()} = "I pressed it already" (CALL) │
└─────────────────────────────────────────────────┘
The "Recipe Card" Analogy
┌─────────────────────────────────────────────────┐
│ HANDLER FUNCTION = RECIPE CARD │
│ │
│ function handleClick() { │
│ alert("Hello!"); │
│ } │
│ │
│ This is like a RECIPE CARD: │
│ ┌─────────────────────────────────────────┐ │
│ │ RECIPE: Chocolate Cake │ │
│ │ │ │
│ │ Ingredients: │ │
│ │ - Flour │ │
│ │ - Sugar │ │
│ │ - Cocoa │ │
│ │ │ │
│ │ Instructions: │ │
│ │ 1. Mix ingredients │ │
│ │ 2. Bake at 350°F │ │
│ │ 3. Enjoy! │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Passing the recipe (CORRECT): │
│ onClick={handleClick} │
│ "Here's the recipe. Make it when ready." │
│ → Card is stored, used later │
│ │
│ Making the cake immediately (WRONG): │
│ onClick={handleClick()} │
│ "I'm making the cake RIGHT NOW!" │
│ → Cake appears immediately, recipe is used up │
│ │
│ Arrow function wrapper (WITH PARAMETERS): │
│ onClick={() => handleClick("special")} │
│ "Here's a note that says 'use this recipe │
│ with SPECIAL ingredients when ready'" │
│ │
│ The wrapper is like a sticky note on the recipe! │
└─────────────────────────────────────────────────┘
Event Naming Convention
┌─────────────────────────────────────────────────┐
│ EVENT NAMING IN REACT │
│ │
│ HTML EVENT → REACT EVENT PROP │
│ ┌─────────────────┬─────────────────────────┐ │
│ │ onclick │ onClick │ │
│ │ onchange │ onChange │ │
│ │ onsubmit │ onSubmit │ │
│ │ onfocus │ onFocus │ │
│ │ onblur │ onBlur │ │
│ │ onmouseover │ onMouseOver │ │
│ │ onmouseenter │ onMouseEnter │ │
│ │ onkeydown │ onKeyDown │ │
│ └─────────────────┴─────────────────────────┘ │
│ │
│ RULE: camelCase in React! │
│ onclick → onClick │
│ onmouseenter → onMouseEnter │
│ │
│ HANDLER NAMING CONVENTION: │
│ ┌─────────────────────────────────────────┐ │
│ │ Event Type │ Handler Name │ │
│ ├─────────────────────────────────────────┤ │
│ │ onClick │ handleClick │ │
│ │ onSubmit │ handleSubmit │ │
│ │ onMouseEnter │ handleMouseEnter │ │
│ │ onChange │ handleChange │ │
│ └─────────────────────────────────────────┘ │
│ │
│ PATTERN: handle + EventName (camelCase) │
│ This tells other developers: "This is an │
│ event handler function!" │
└─────────────────────────────────────────────────┘
Common Patterns Cheat Sheet
┌─────────────────────────────────────────────────┐
│ COMMON EVENT HANDLING PATTERNS │
│ │
│ 1. SIMPLE HANDLER (No parameters): │
│ ┌─────────────────────────────────────────┐ │
│ │ function handleClick() { │ │
│ │ console.log("Clicked!"); │ │
│ │ } │ │
│ │ <button onClick={handleClick}> │ │
│ └─────────────────────────────────────────┘ │
│ │
│ 2. HANDLER WITH PARAMETERS: │
│ ┌─────────────────────────────────────────┐ │
│ │ function handleClick(id) { │ │
│ │ console.log(id); │ │
│ │ } │ │
│ │ <button onClick={() => handleClick(1)}>│ │
│ └─────────────────────────────────────────┘ │
│ │
│ 3. INLINE ARROW (Simple): │
│ ┌─────────────────────────────────────────┐ │
│ │ <button onClick={() => alert("Hi!")}> │ │
│ └─────────────────────────────────────────┘ │
│ │
│ 4. EVENT OBJECT ACCESS: │
│ ┌─────────────────────────────────────────┐ │
│ │ function handleClick(event) { │ │
│ │ console.log(event.target); │ │
│ │ } │ │
│ │ <button onClick={handleClick}> │ │
│ └─────────────────────────────────────────┘ │
│ │
│ NEVER DO THIS: │
│ ┌─────────────────────────────────────────┐ │
│ │ <button onClick={handleClick()}> │ │
│ │ // Calls function immediately! │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Practice Exercises
Exercise 1: Create a Counter
Create a counter with increment and decrement buttons:
function Counter() {
// TODO: Add state and handlers
return (
<div>
<h1>Count: {/* show count here */}</h1>
<button>Decrement</button>
<button>Increment</button>
</div>
);
}
Solution:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
function handleIncrement() {
setCount(c => c + 1);
}
function handleDecrement() {
setCount(c => c - 1);
}
return (
<div>
<h1>Count: {count}</h1>
<button onClick={handleDecrement}>Decrement</button>
<button onClick={handleIncrement}>Increment</button>
</div>
);
}
Exercise 2: Fix the Bug
This code has a bug. The alert shows immediately on page load:
function App() {
function sayHello() {
alert("Hello!");
}
return (
<button onClick={sayHello()}>
Click me
</button>
);
}
Bug: sayHello() calls the function immediately.
Solution:
function App() {
function sayHello() {
alert("Hello!");
}
return (
<button onClick={sayHello}> {/* Removed () */}
Click me
</button>
);
}
Exercise 3: Create a Toggle Button
Create a button that toggles between "ON" and "OFF":
function Toggle() {
// TODO: Create toggle functionality
return (
<button>
{/* Show ON or OFF */}
</button>
);
}
Solution:
import { useState } from 'react';
function Toggle() {
const [isOn, setIsOn] = useState(false);
function handleToggle() {
setIsOn(on => !on);
}
return (
<button
onClick={handleToggle}
style={{
backgroundColor: isOn ? '#4caf50' : '#f44336',
color: 'white',
padding: '10px 20px'
}}
>
{isOn ? 'ON' : 'OFF'}
</button>
);
}
Key Takeaways
| Concept | What It Means | Example |
|---|---|---|
| onClick | Click event handler prop | <button onClick={handleClick}> |
| Handler Function | Function that runs on event | function handleClick() { ... } |
| Pass Reference | Give function to React (don't call!) | onClick={handleClick} |
| Arrow Function | Inline function definition | onClick={() => alert("Hi!")} |
| Parameters | Pass data using arrow wrapper | onClick={() => handleClick(id)} |
| Naming | handle + EventName convention | handleClick, handleSubmit |
| Multiple Events | Different props for different events | onClick, onMouseEnter |
The Event Handling Pattern:
function Component() {
// 1. Define handler (inside component)
function handleEvent() {
// Do something
}
return (
// 2. Pass to event prop (NO PARENTHESES!)
<button onClick={handleEvent}>
Click me
</button>
);
}
Golden Rules:
- Use camelCase -
onClicknotonclick - Pass reference -
onClick={handleClick}notonClick={handleClick()} - Name handlers - Start with
handle(handleClick, handleSubmit) - Define inside component - So they can access props/state
- Use arrow wrapper for parameters -
onClick={() => handleClick(id)}
One Sentence Summary: > "In React, you handle events by passing a function reference (not calling it!) to special camelCase props like onClick - define your handler function inside the component using the 'handle' naming convention, and wrap it in an arrow function if you need to pass custom parameters!"