React.js course ยท Lecture 8 of 27

Events in React Masterclass

A masterclass tutorial covering Click Events, Change Events, Submit Events, Keyboard Events, Mouse Events, Event Handlers, Passing Arguments, Synthetic Events, preventDefault(), Event Bubbling & stopPropagation(), Pitfalls, and Interview Questions.

  • 30 min read
  • Beginner to Intermediate
  • 10 topics
  • 20 Sept 2026
  • Ravindra Nath Jha

What are Events in React?

Web applications are driven by user actions: clicking buttons, typing in text boxes, hovering over images, submitting forms, or pressing keyboard shortcuts.

In React, handling events is syntactically similar to handling events on DOM elements, with a few key differences in naming, binding, and event delegation.

Key Differences Between HTML Events and React Events

FeatureHTML DOM EventsReact Synthetic Events
Naming ConventionLowercase (onclick, onchange)CamelCase (onClick, onChange)
Handler TypeString: onclick="handleClick()"Function Reference: onClick={handleClick}
Default PreventionReturn falseMust explicitly call e.preventDefault()
Event DelegationDirect node bindingAutomatic root delegation (React Root element)

SyntheticEvent System in React

When an event fires in React, React passes a SyntheticEvent object wrapper to your handler function rather than a raw browser native event.

Why SyntheticEvent?

  • Cross-Browser Consistency: Normalizes browser inconsistencies between Chrome, Firefox, Safari, and Edge.
  • High Performance: Uses Event Delegation at the root root container node to conserve system memory.

Common Event Types in React

  1. Click Events: onClick, onDoubleClick
  2. Change Events: onChange (Fires on input, select, textarea value modification)
  3. Form Submit Events: onSubmit (Fires when form is submitted via Enter key or Submit button)
  4. Keyboard Events: onKeyDown, onKeyUp, onKeyPress
  5. Mouse Events: onMouseEnter, onMouseLeave, onMouseMove
  6. Focus Events: onFocus, onBlur

Passing Arguments to Event Handlers

If your handler needs additional custom arguments (e.g. passing a product ID), wrap the function invocation inside an arrow function:

JavaScript
// โœ… CORRECT: Arrow function wrapper
<button onClick={() => handleDeleteProduct(product.id)}>Delete Item</button>

// โŒ WRONG: Invokes function immediately during rendering!
<button onClick={handleDeleteProduct(product.id)}>Delete Item</button>

Form Submission & preventDefault()

By default, HTML forms reload the browser page when submitted. In Single Page Applications (SPAs), we must call e.preventDefault() to cancel page reloads and process inputs in JavaScript:

JavaScript
function ContactForm() {
  const handleSubmit = (e) => {
    e.preventDefault(); // Prevents browser page refresh!
    console.log("Form submitted via AJAX!");
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" placeholder="Your name" />
      <button type="submit">Submit Form</button>
    </form>
  );
}

Event Bubbling & Stopping Propagation (stopPropagation)

In the DOM, events bubble up from child nodes to parent nodes.

If clicking a child button triggers a parent card click handler unexpectedly, use e.stopPropagation():

JavaScript
function Card({ onCardClick, onDelete }) {
  return (
    <div onClick={onCardClick} className="card">
      <h3>Card Title</h3>
      <button 
        onClick={(e) => {
          e.stopPropagation(); // Stops click from bubbling up to parent card!
          onDelete();
        }}
      >
        Delete Card
      </button>
    </div>
  );
}

Common Mistakes with Event Handlers

  1. Invoking handler immediately: onClick={handleClick()} instead of onClick={handleClick}.
  2. Forgetting preventDefault() on forms: Causes full browser page reload and loss of application state.
  3. Confusing event.target and event.currentTarget:
  • e.target = The exact element that triggered the event (e.g., inner icon).
  • e.currentTarget = The element that the event listener is attached to.

Top React Interview Questions on Events

Q1: What is a SyntheticEvent in React?

*Answer*: SyntheticEvent is a cross-browser wrapper around the browser's native event object, standardizing properties and handling event delegation at the root root node.

Q2: What is the difference between e.target and e.currentTarget?

*Answer*: e.target points to the target element where the event originated, whereas e.currentTarget points to the element handling the event listener.

Q3: How do you prevent event bubbling in React?

*Answer*: Invoke e.stopPropagation() inside the child event handler.

Practical Hands-On Exercise โ€” Complete Event Explorer Component

Here is a complete interactive application handling click, input change, form submission, keyboard shortcuts, argument passing, and propagation stopping:

JavaScript
// Complete Masterclass Events Showcase (src/App.jsx)
import React, { useState } from 'react';

export default function App() {
  const [inputText, setInputText] = useState("");
  const [lastKey, setLastKey] = useState("None");
  const [logs, setLogs] = useState([]);

  const addLog = (msg) => {
    setLogs(prev => [`[${new Date().toLocaleTimeString()}] ${msg}`, ...prev.slice(0, 4)]);
  };

  const handleFormSubmit = (e) => {
    e.preventDefault();
    addLog(`Submitted Form with text: "${inputText}"`);
    setInputText("");
  };

  const handleKeyDown = (e) => {
    setLastKey(e.key);
    if (e.key === 'Enter' && e.ctrlKey) {
      addLog("Shortcut Triggered: Ctrl + Enter!");
    }
  };

  return (
    <div style={{ maxWidth: "600px", margin: "30px auto", padding: "20px", background: "#f8fafc", borderRadius: "16px" }}>
      <h2 style={{ color: "#002057" }}>Lecture 8: React Events Masterclass Explorer</h2>

      {/* Interactive Form */}
      <form onSubmit={handleFormSubmit} style={{ marginBottom: "20px" }}>
        <label style={{ display: "block", marginBottom: "6px", fontWeight: "bold" }}>Type Something & Press Enter:</label>
        <input 
          type="text"
          value={inputText}
          onChange={(e) => setInputText(e.target.value)}
          onKeyDown={handleKeyDown}
          placeholder="Try pressing Ctrl + Enter..."
          style={{ width: "100%", padding: "10px", borderRadius: "6px", border: "1px solid #cbd5e1", marginBottom: "10px" }}
        />
        <button type="submit" style={{ background: "#2506ad", color: "#fff", border: "none", padding: "10px 16px", borderRadius: "6px", fontWeight: "bold" }}>
          Submit Form
        </button>
      </form>

      {/* Event Bubbling Demo */}
      <div 
        onClick={() => addLog("Parent Card Clicked!")}
        style={{ padding: "20px", background: "#e2e8f0", borderRadius: "10px", marginBottom: "20px", cursor: "pointer" }}
      >
        <p style={{ margin: 0, fontWeight: "bold" }}>Parent Card Container (Clickable)</p>
        <button 
          onClick={(e) => {
            e.stopPropagation(); // Stops propagation!
            addLog("Child Button Clicked (Propagation Stopped!)");
          }}
          style={{ marginTop: "10px", background: "#059669", color: "#fff", border: "none", padding: "8px 12px", borderRadius: "6px" }}
        >
          Child Button (Stops Propagation)
        </button>
      </div>

      {/* Status Log */}
      <div style={{ padding: "12px", background: "#0f172a", color: "#38bdf8", borderRadius: "8px", fontFamily: "monospace" }}>
        <div>Last Key Pressed: <strong>{lastKey}</strong></div>
        <hr style={{ borderColor: "#334155" }} />
        {logs.map((log, idx) => (
          <div key={idx}>{log}</div>
        ))}
      </div>
    </div>
  );
}