Course topics

By WebNest Studio Engineering Team

React Tutorial

Handling Events in React

React lets you respond to user interactions — clicks, typing, form submissions, mouse movement — by attaching event handler functions directly to JSX elements. Event handling in React looks similar to plain HTML's inline event attributes, but it works differently under the hood and follows JavaScript naming conventions instead of HTML ones.

Instead of lowercase HTML attributes like onclick="..." with a string of code, React uses camelCase props like onClick={handleClick}, where the value is an actual JavaScript function reference, not a string to be evaluated.

Why it matters

Clicks, typing and form submissions are how users drive an application. React's event handling looks like HTML's but differs in ways that trip people up: handlers are functions passed by reference, not strings, and a handler that is called instead of passed runs on every render.

Attaching Event Handlers

Common event props include onClick for clicks, onChange for input value changes, onSubmit for form submissions, and onMouseOver, onKeyDown, and many others that mirror native DOM events. You pass a function reference, not a function call: onClick={handleClick} is correct, while onClick={handleClick()} would incorrectly invoke the function immediately during render instead of waiting for the click.

Synthetic Events

React wraps native browser events in a cross-browser wrapper called a SyntheticEvent, which normalizes behavior across different browsers and provides the same familiar API (event.target, event.preventDefault(), event.stopPropagation()) regardless of which underlying browser event actually fired. This means you can write one consistent set of event-handling code without worrying about browser-specific quirks.

Passing Arguments to Handlers

Because onClick expects a function reference, passing extra arguments requires wrapping the call in an inline arrow function, for example onClick={() => handleDelete(item.id)}. This creates a new function on every render, which is usually fine for typical UI interactions, though it is something to be mindful of in performance-sensitive lists.

Example

Handling a click event and a form submission with preventDefault

JavaScript
import { useState } from 'react';

function SubscribeForm() {
  const [email, setEmail] = useState('');
  const [submitted, setSubmitted] = useState(false);

  function handleSubmit(event) {
    event.preventDefault(); // stops the browser's default full-page reload
    setSubmitted(true);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(event) => setEmail(event.target.value)}
        placeholder="you@example.com"
      />
      <button type="submit">Subscribe</button>
      {submitted && <p>Thanks, {email}! You are subscribed.</p>}
    </form>
  );
}

export default SubscribeForm;
Output
Typing into the input updates the field as you type; clicking "Subscribe" prevents the page from reloading and instead shows "Thanks, you@example.com! You are subscribed." below the form.

Common Mistakes

  • Writing onClick={handleClick()} instead of onClick={handleClick}, which calls the function immediately during rendering rather than when the element is clicked.
  • Forgetting to call event.preventDefault() inside a form's onSubmit handler, causing an unwanted full-page reload.
  • Assuming React event handlers receive the raw native browser event with no differences — React actually passes a SyntheticEvent wrapper with a normalized API.
  • Defining a new inline arrow function for every list item's handler without considering the performance cost in very large, frequently re-rendered lists.

Exercise

Do this in src/App.jsx of a Vite + React project. Build a small form with a text input and a submit button. When the form is submitted, stop the browser from reloading the page and show the text that was entered in a paragraph below the form.

Expected result: typing a name and pressing Enter or the button shows "Hello, " followed by the name, without the page reloading.

JavaScript · starter code
import { useState } from "react";

export default function App() {
  const [name, setName] = useState("");
  const [greeting, setGreeting] = useState("");

  // TODO: function handleSubmit(event): prevent the default action and set the greeting

  return (
    <form /* TODO: attach the submit handler */>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button type="submit">Greet</button>
      <p>{greeting}</p>
    </form>
  );
}
Show hints
  • The handler receives the event object; event.preventDefault() stops the page from reloading.
  • Pass the function itself to the form: onSubmit={handleSubmit}, without parentheses.
Show solution
JavaScript · solution
import { useState } from "react";

export default function App() {
  const [name, setName] = useState("");
  const [greeting, setGreeting] = useState("");

  function handleSubmit(event) {
    event.preventDefault();
    setGreeting("Hello, " + name);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button type="submit">Greet</button>
      <p>{greeting}</p>
    </form>
  );
}

Quick quiz

1. What is wrong with <button onClick={handleClick()}>?

  • A. Nothing
  • B. The function is called during rendering, and its return value is used as the handler
  • C. onClick must be lower case
  • D. Buttons cannot have click handlers
Show answer

B. Pass the function itself: onClick={handleClick}.

2. How do you pass an argument to an event handler?

  • A. onClick={remove(id)}
  • B. onClick="remove(id)"
  • C. onClick={remove, id}
  • D. onClick={() => remove(id)}
Show answer

D. The arrow function is what gets called on the click, and it then calls remove with the argument.

3. How are event names written in JSX?

  • A. camelCase, such as onClick and onChange
  • B. Lower case, such as onclick
  • C. With a colon, such as on:click
  • D. In upper case
Show answer

A. The value is a function, not a string of code.

Interview questions

What is a synthetic event?

Show answer

It is React's wrapper around the browser's native event. It has the same interface, with methods such as preventDefault() and stopPropagation() and properties such as target, and behaves the same in every browser. React attaches its listeners at the root of the application and dispatches events to the handlers itself. The underlying browser event is available as event.nativeEvent.

How does a child component notify its parent that something happened?

Show answer

The parent passes a function to the child as a prop, such as onAdd, and the child calls it when the event occurs, passing any data as arguments. The parent's function then updates the parent's state. Data flows down through props and events flow up through these callback props, which keeps the flow of data in one direction.

Key Points to Remember

  • React event props use camelCase (onClick, onChange, onSubmit) and take a function reference, not a string.
  • React wraps native browser events in SyntheticEvents for consistent cross-browser behavior.
  • Use event.preventDefault() to stop default browser behavior, such as a form causing a page reload.
  • Wrap a handler in an inline arrow function when it needs extra arguments beyond the event object.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Shows a live preview of plain HTML, CSS and JavaScript. JSX needs a React project on your computer. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

These examples need a project environment on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering