Skip to content

Join the Seedly owners community →

React

Event Handling

Learn how to respond to user interactions like clicks, typing, and form submissions in React

Written by 11 min read1 activity
Sprout, your presenter

Sprout presents

Clicks, typing and form submissions, each with its own handler. We will also prevent default behavior, which sounds ominous but is quite routine.Clicks, typing and form submissions, each with its own handler. We will also prevent default behavior, which sounds ominous but is quite routine.

Sprout presses a button on a wooden box and a carved bird pops out of its little door
An event handler runs when the user does something

Every interactive app has to respond to what people do. They click buttons, type in fields, submit forms and hover over stuff. In React you handle all of that with event handlers, which are just functions that run when something happens.

Your First Event Handler#

In React you attach event handlers right onto JSX elements using camelCase props like onClick, onChange and onSubmit.

function AlertButton() {
  function handleClick() {
    alert('You clicked me!');
  }
 
  return <button onClick={handleClick}>Click me</button>;
}

Look closely here. You pass the function itself (handleClick), and you do NOT pass a function call (handleClick()). If you wrote onClick={handleClick()}, the function would fire the moment the component renders instead of waiting for somebody to click.

Inline Event Handlers#

For short handlers, you can write an arrow function right there in the JSX.

import { useState } from 'react';
 
function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}

Inline handlers are great for simple one-liners. Once the logic gets longer, pull it out into a named function so future you can actually read it.

Common Event Types#

React supports all the standard browser events. These are the ones you'll use the most.

EventTriggers WhenCommon Uses
onClickUser clicks an elementButtons, links, cards
onChangeInput value changesText inputs, checkboxes, selects
onSubmitForm is submittedForm handling
onKeyDownKey is pressedKeyboard shortcuts, Enter to submit
onMouseEnterCursor enters an elementTooltips, hover effects
onMouseLeaveCursor leaves an elementHiding hover effects
onFocusElement gains focusShowing helper text
onBlurElement loses focusValidation on field exit

The Event Object#

Every event handler gets handed an event object with the details of what just happened.

function KeyLogger() {
  function handleKeyDown(event) {
    console.log(`Key pressed: ${event.key}`);
    if (event.key === 'Enter') {
      console.log('User pressed Enter!');
    }
  }
 
  return <input onKeyDown={handleKeyDown} placeholder="Press any key..." />;
}

A few properties on the event object you'll reach for constantly.

  • event.target - the DOM element that triggered the event
  • event.target.value - the current value of an input
  • event.key - which keyboard key got pressed
  • event.preventDefault() - stops the browser's default action

Handling Text Input#

To keep track of what somebody types, pair onChange with state.

function SearchBox() {
  const [query, setQuery] = useState('');
 
  function handleChange(event) {
    setQuery(event.target.value);
  }
 
  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={handleChange}
        placeholder="Search..."
      />
      <p>You're searching for: {query}</p>
    </div>
  );
}

That's called a controlled input, because React controls the input's value through state. Every keystroke updates state, which re-renders the component, which updates the value on screen. Round and round it goes.

Preventing Default Behavior#

Sprout pulls a lever that diverts a toy train onto a side track away from its usual route
preventDefault stops the browser doing what it normally would

Browsers have built-in behaviors for certain events. Forms reload the page when you submit them, and links navigate you away. Use event.preventDefault() to stop those defaults in their tracks.

function LoginForm() {
  const [email, setEmail] = useState('');
 
  function handleSubmit(event) {
    event.preventDefault(); // Stop page reload!
    console.log('Submitting:', email);
    // Send data to your API instead
  }
 
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={e => setEmail(e.target.value)}
      />
      <button type="submit">Log In</button>
    </form>
  );
}

Passing Arguments to Handlers#

Sometimes your handler needs a bit of extra info. The move is to wrap the handler in an arrow function.

function FruitList() {
  const fruits = ['Apple', 'Banana', 'Cherry'];
 
  function handleSelect(fruit) {
    alert(`You selected: ${fruit}`);
  }
 
  return (
    <ul>
      {fruits.map(fruit => (
        <li key={fruit}>
          <button onClick={() => handleSelect(fruit)}>
            {fruit}
          </button>
        </li>
      ))}
    </ul>
  );
}

The arrow function () => handleSelect(fruit) creates a brand new function for each item, and each one remembers which fruit to pass along.

Handling Multiple Inputs#

When a form has a bunch of fields, you can get away with one handler by using the input's name attribute.

function ProfileForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    bio: ''
  });
 
  function handleChange(event) {
    const { name, value } = event.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  }
 
  return (
    <form>
      <input name="name" value={formData.name} onChange={handleChange} />
      <input name="email" value={formData.email} onChange={handleChange} />
      <textarea name="bio" value={formData.bio} onChange={handleChange} />
    </form>
  );
}

The computed property [name]: value sets the right field based on whichever input fired the event. One handler, all three fields handled.

TL;DR#

  • Event handlers are functions you pass to JSX elements through camelCase props (onClick, onChange, onSubmit)
  • Pass the function reference (handleClick), and don't call it (handleClick())
  • The event object gives you details like event.target.value and event.key
  • Use event.preventDefault() to stop default browser behaviors (like a form reloading the page)
  • Controlled inputs pair value from state with onChange to track what people type
  • Wrap handlers in arrow functions when you need to pass extra arguments

What's Next?#

You know how to handle events inside a single component now. But what happens when a child component needs to tell its parent that something happened? Next lesson is Props and Data Flow, all about passing data down and sending events back up the component tree...

This lesson ends with a short activity.