← Back to Chapters

Handling Events in React

⚛️ Handling Events in React

React’s event system lets components respond to user actions like clicks, typing, form submissions, and key presses, using a cross-browser wrapper called SyntheticEvent.

You can handle events in both function components (with hooks) and class components (with methods and bindings).

⚡ Quick Overview

  • React wraps native browser events into a cross-browser SyntheticEvent object.
  • Event handlers are passed as function references (not executed immediately).
  • Function components typically use arrow functions for handlers.
  • Class components need proper binding or arrow-function fields for handlers.
  • You can access the event object, prevent default behaviour, and control propagation.

? Key Concepts

  • JSX event props — use attributes like onClick, onChange, onSubmit.
  • Function component handlers — defined with arrow functions and passed by reference.
  • Class component handlers — defined as methods and bound to this.
  • Event object — first parameter, usually named e or event, is a SyntheticEvent.
  • Default behaviour — use e.preventDefault() to stop form submission, link navigation, etc.
  • Event propagation — events bubble; use e.stopPropagation() to stop bubbling.
  • Passing arguments — wrap handler calls inside arrow functions to pass extra data safely.

? Syntax & Theory

Function component event handler (typical pattern)

In function components, you define an event handler and pass the function reference to a JSX attribute:

  • onClick={handleClick} ✅ — passes the function itself.
  • onClick={handleClick()} ❌ — calls the function immediately during render.

Class component event handler (two main options)

  • Bind the method in the constructor using this.methodName = this.methodName.bind(this).
  • Or define the handler as a class field arrow function: handleClick = () => {...} (modern style).

Event object

React passes a SyntheticEvent object to handlers, which normalizes behaviour across browsers and exposes properties like target, type, currentTarget, etc.

? Code Examples

⚙️ Handling Events in Function Components

A basic click handler in a function component:

? View Code Example
// Simple click handler in a function component
function ButtonClick() {
const handleClick = () => {
alert("You clicked the button!");
};

return (
<button className="btn btn-primary" onClick={handleClick}>
Click Me
</button>
);
}

Here, onClick={handleClick} is a function reference. The function runs only when the button is clicked.

?️ Accessing the Event Object

The first argument to the handler is a SyntheticEvent. You can read values from e.target:

? View Code Example
// Reading input value using the event object
function InputHandler() {
const handleChange = (e) => {
console.log("Typed:", e.target.value);
};

return (
<input
type="text"
className="form-control w-50"
placeholder="Type something..."
onChange={handleChange}
/>
);
}

Every time the user types, React calls handleChange with a fresh SyntheticEvent, whose target.value holds the current input text.

? Handling Events in Class Components

In class components, handlers are methods that must be bound to the component instance so that this works correctly.

✅ Example 1: Binding in Constructor

? View Code Example
// Class component using constructor binding
class Clicker extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState({ count: this.state.count + 1 });
}

render() {
return (
<button className="btn btn-success" onClick={this.handleClick}>
Count: {this.state.count}
</button>
);
}
}

✅ Example 2: Using Arrow Function (Recommended)

? View Code Example
// Class component using an arrow-function handler
class ArrowClicker extends React.Component {
state = { clicks: 0 };

handleClick = () => {
this.setState({ clicks: this.state.clicks + 1 });
};

render() {
return (
<button className="btn btn-warning" onClick={this.handleClick}>
Clicked: {this.state.clicks}
</button>
);
}
}

? Passing Arguments to Event Handlers

To pass extra data to a handler, wrap the call in an arrow function so that it runs only when the event fires:

? View Code Example
// Passing extra data to an event handler
function GreetUser() {
const greet = (name) => alert(`Hello, ${name}!`);

return (
<div>
<button className="btn btn-info me-2" onClick={() => greet("Ananya")}>
Greet Ananya
</button>
<button className="btn btn-secondary" onClick={() => greet("Rahul")}>
Greet Rahul
</button>
</div>
);
}

? Preventing Default Behaviour

Forms try to submit and reload the page by default. Use e.preventDefault() to stop that and handle the data in JavaScript instead:

? View Code Example
// Preventing default form submission
function FormSubmit() {
const handleSubmit = (e) => {
e.preventDefault();
alert("Form Submitted!");
};

return (
<form onSubmit={handleSubmit} className="p-3 border rounded shadow-sm w-50">
<input className="form-control mb-2" placeholder="Enter your name" />
<button className="btn btn-primary" type="submit">Submit</button>
</form>
);
}

? Event Propagation (Bubbling)

Events bubble from child to parent. If you want to stop a click from reaching a parent, call e.stopPropagation():

? View Code Example
// Stopping an event from bubbling to the parent
function PropagationExample() {
const parentClick = () => alert("Parent clicked!");
const childClick = (e) => {
e.stopPropagation();
alert("Child clicked!");
};

return (
<div className="p-3 border" onClick={parentClick}>
Parent
<button className="btn btn-danger ms-2" onClick={childClick}>
Child Button
</button>
</div>
);
}

? Live Output & Behaviour Explanation

What happens when this code runs?

  • ButtonClick — clicking the button shows an alert saying "You clicked the button!".
  • InputHandler — every keystroke logs Typed: <current text> to the console.
  • Clicker / ArrowClicker — each click increments the counter displayed on the button.
  • GreetUser — clicking a button shows an alert greeting the specific name you passed.
  • FormSubmit — submitting the form shows an alert and does not reload the page.
  • PropagationExample:
    • Clicking the parent area shows "Parent clicked!".
    • Clicking the child button shows only "Child clicked!" because stopPropagation() prevents the parent handler from running.

? Common Use Cases

  • Buttons that submit forms, toggle modals, or trigger API requests.
  • Inputs that update component state in real time (search bars, filters, controlled forms).
  • Keyboard shortcuts using onKeyDown / onKeyUp.
  • Interactive UI elements like dropdowns, tabs, carousels, and accordions.
  • Stopping propagation for nested clickable elements (e.g., cards with inner buttons/links).

? Tips & Best Practices

  • Always pass a function reference to event props (e.g., onClick={handleClick}).
  • Use arrow functions for handlers in both function and class components for concise syntax.
  • In class components, either bind handlers in the constructor or use arrow-function class fields.
  • Keep event handlers small and delegate complex logic to helper functions.
  • Remember that the event object is a SyntheticEvent; if you need it asynchronously, call e.persist().
  • Use preventDefault() and stopPropagation() intentionally to control browser behaviour and bubbling.
  • Name handlers clearly, e.g. handleClick, handleSubmit, handleChange, for readability.

? Try It Yourself

  1. Create a button that increments a counter using:
    • a function component with useState.
    • a class component with state and this.setState.
  2. Build a form that:
    • prevents page reload using e.preventDefault(), and
    • shows the input text in an alert when submitted.
  3. Demonstrate event propagation:
    • create a parent div with an onClick handler.
    • add a child button that calls e.stopPropagation() in its handler.
  4. Log the entire event object in different handlers using console.log(e) and inspect:
    • e.target vs e.currentTarget
    • e.type and other useful properties.

Goal: Master event handling in both functional and class components, including how to bind methods, use arrow functions, access event objects, and control default behaviour and propagation.