React Event Handlers

Event handlers let you respond to user actions like clicks, key presses, form input, and mouse movement. React events work similarly to native browser events, with a few differences.

How React events work

React wraps native browser events in its own SyntheticEvent object. This normalizes behaviour across different browsers so you do not have to worry about inconsistencies.

Event names in React are camelCase, not lowercase:

  • HTML: onclick
  • React: onClick

You pass a function reference (not a string) as the event handler:

// HTML (do not do this in React):
<button onclick="handleClick()">Click</button>

// React (correct):
<button onClick={handleClick}>Click</button>

Adding event handlers

The most straightforward way is to define a function and pass it to the event prop:

function App() {
  function handleClick() {
    console.log('Button clicked');
  }

  return <button onClick={handleClick}>Click me</button>;
}

You can also use an inline arrow function:

function App() {
  return (
    <button onClick={() => console.log('Button clicked')}>
      Click me
    </button>
  );
}

Both work. Named functions are easier to test and reuse. Inline arrows are convenient for short handlers or when you need to pass arguments.

The event object

React passes the event object automatically to your handler. You can access it to read input values, prevent default behaviour, and more:

function SearchBar() {
  function handleChange(event) {
    console.log(event.target.value);
  }

  return <input type="text" onChange={handleChange} />;
}

Preventing default behaviour

Many browser events have a default action: clicking a link navigates, submitting a form reloads the page. Call event.preventDefault() to stop that:

function ContactForm() {
  function handleSubmit(event) {
    event.preventDefault();
    // now handle the submission yourself
    console.log('Form submitted');
  }

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

Passing arguments to event handlers

If you need to pass extra data to a handler, wrap it in an arrow function:

function ItemList({ items }) {
  function handleDelete(id) {
    console.log('Deleting item', id);
  }

  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>
          {item.name}
          <button onClick={() => handleDelete(item.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

The arrow function () => handleDelete(item.id) creates a new function that, when called, invokes handleDelete with the specific id.

Practical examples

onClick

function Counter() {
  const [count, setCount] = React.useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

onChange (input)

function TextInput() {
  const [value, setValue] = React.useState('');

  return (
    <input
      type="text"
      value={value}
      onChange={(e) => setValue(e.target.value)}
      placeholder="Type something..."
    />
  );
}

onSubmit (form)

function LoginForm() {
  const [email, setEmail] = React.useState('');

  function handleSubmit(e) {
    e.preventDefault();
    console.log('Submitted:', email);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button type="submit">Log in</button>
    </form>
  );
}

onKeyDown (keyboard)

Use onKeyDown to detect key presses. Note: onKeyPress is deprecated and should not be used in new code.

function SearchInput() {
  function handleKeyDown(event) {
    if (event.key === 'Enter') {
      console.log('Search triggered');
    }
    if (event.key === 'Escape') {
      console.log('Search cancelled');
    }
  }

  return <input type="text" onKeyDown={handleKeyDown} />;
}

onMouseEnter / onMouseLeave (hover)

function HoverCard() {
  const [hovered, setHovered] = React.useState(false);

  return (
    <div
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{ background: hovered ? '#f0f8ff' : '#fff', padding: 16 }}
    >
      {hovered ? 'You are hovering!' : 'Hover over me'}
    </div>
  );
}

Supported events

React supports all standard DOM events. Here is a reference:

  • Clipboard: onCopy onCut onPaste
  • Composition: onCompositionEnd onCompositionStart onCompositionUpdate
  • Keyboard: onKeyDown onKeyUp (onKeyPress is deprecated, use onKeyDown)
  • Focus: onFocus onBlur
  • Form: onChange onInput onInvalid onReset onSubmit
  • Generic: onError onLoad
  • Mouse: onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp
  • Pointer: onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut
  • Selection: onSelect
  • Touch: onTouchCancel onTouchEnd onTouchMove onTouchStart
  • UI: onScroll
  • Wheel: onWheel
  • Media: onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend onTimeUpdate onVolumeChange onWaiting
  • Image: onLoad onError
  • Animation: onAnimationStart onAnimationEnd onAnimationIteration
  • Transition: onTransitionEnd
  • Other: onToggle

For the full event reference, see the React DOM events documentation .

Common mistakes

Calling the function instead of passing it.

// Wrong: handleClick() is called immediately when the component renders
<button onClick={handleClick()}>Click</button>

// Correct: pass a reference, React calls it when the button is clicked
<button onClick={handleClick}>Click</button>

If your handler needs arguments, use an arrow function to wrap it:

<button onClick={() => handleDelete(item.id)}>Delete</button>

Using onKeyPress.

onKeyPress is deprecated. Use onKeyDown instead. onKeyDown fires on every key press including modifier keys, while the now-removed onKeyPress only fired for printable characters.

What to learn next