Handling Events

Handling events in React is very similar to handling events on DOM elements, with a few syntax differences:

  • React events are named using camelCase (e.g., onClick instead of onclick).
  • With JSX, you pass a function as the event handler, rather than a string.

JavaScript


import React from 'react';

function ActionButton() {
  // Define the event handler function
  const handleClick = () => {
    alert('Button was clicked!');
  };

  return (
    // Pass the function reference to the onClick prop
    <button onClick={handleClick}>
      Click Me
    </button>
  );
}

You can also define the handler inline using an arrow function, which is useful for passing arguments.

JavaScript


function Item({ message }) {
  const showAlert = () => {
    alert(message);
  };

  return <button onClick={showAlert}>Show Message</button>;
}
Forms: The Controlled Component

The most common and recommended way to handle forms in React is the controlled component pattern. It's called "controlled" because the React component that renders the form controls what's in that form.

This is achieved by making the component's state the single source of truth for the input's value.

Here's how it works:

  1. Create a piece of state to hold the value of the input.
  2. Set the value attribute of the input element to this state variable.
  3. Use the onChange event handler to call your state update function whenever the user types.

JavaScript


import React, { useState } from 'react';

function NameForm() {
  // 1. Create a state variable to hold the input's value
  const [name, setName] = useState('');

  const handleChange = (event) => {
    // 3. Update the state on every keystroke
    setName(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault(); // Prevent page refresh
    alert(`A name was submitted: ${name}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>Name:</label>
      <input
        type="text"
        // 2. The input's value is tied directly to the state
        value={name}
        onChange={handleChange}
      />
      <button type="submit">Submit</button>
    </form>
  );
}

With this pattern, the input's value and the component's state are always in sync. This makes it easy to validate input, conditionally disable buttons, or format the input value.

The Uncontrolled Component

An uncontrolled component is closer to traditional HTML. The form data is handled by the DOM itself, not by the React component. Instead of writing an event handler for every state update, you use a ref to "pull" the value from the DOM when you need it (e.g., inside the onSubmit handler).

You'll learn about useRef in a later tutorial, but here's a preview:

JavaScript


import React, { useRef } from 'react';

function UncontrolledNameForm() {
  // Create a ref to hold a reference to the input DOM element
  const inputRef = useRef(null);

  const handleSubmit = (event) => {
    event.preventDefault();
    // Access the input's current value directly from the DOM
    alert(`A name was submitted: ${inputRef.current.value}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>Name:</label>
      {/* The ref is attached to the input element */}
      <input type="text" ref={inputRef} />
      <button type="submit">Submit</button>
    </form>
  );
}

Uncontrolled components can be simpler for very basic forms, but controlled components are generally more powerful and are the recommended approach in React.