Home/Learn/React/Handling Events

Handling Events

Beginner
Fundamentals

Pass a function, do not call one. Most early event bugs are one pair of parentheses in the wrong place.

Overview

React event props take a function reference that React will call later. Writing onClick={handleClick()} calls it during render instead — which usually triggers a state update, which triggers a render, which calls it again. Beyond that, React events are close enough to DOM events that your browser knowledge transfers, with two differences worth knowing: the naming is camelCase, and React attaches a single listener at the root rather than one per element.

Passing Handlers

Reference, not call. Arrow wrappers are how you pass arguments.

onClick={fn}, not onClick={fn()}
<button onClick={handleRun}>Run</button>       // correct — a reference
<button onClick={handleRun()}>Run</button>     // WRONG — calls it now

// Passing an argument needs a wrapper
<button onClick={() => onOpen(problem.slug)}>Open</button>

// Inline is fine. "It creates a new function every render" is true
// and almost never the reason a page is slow — measure before
// contorting the code around it.

// The event object
function handleSubmit(e) {
  e.preventDefault()          // stop the browser navigating
  e.stopPropagation()         // stop it reaching parent handlers
  e.currentTarget.value
}

// Common handlers
onChange onInput onSubmit onKeyDown onFocus onBlur
onMouseEnter onPointerDown onScroll

How React Delivers Events

One listener at the root, and a normalised event object.

Delegation at the root, and SyntheticEvent
// React does NOT attach a listener to each element. It attaches one
// per event type at the root container and dispatches from there.
// So handlers work for elements added later, and adding a thousand
// rows does not add a thousand listeners.

// The event you receive is a SyntheticEvent — a cross-browser
// wrapper. The real DOM event is on e.nativeEvent when you need it.

// Because React listens at the root, a document-level listener you
// add yourself runs BEFORE React's handlers, which matters for
// "click outside to close" logic:
useEffect(() => {
  const onDocClick = (e) => {
    if (!ref.current?.contains(e.target)) setOpen(false)
  }
  document.addEventListener('mousedown', onDocClick)
  return () => document.removeEventListener('mousedown', onDocClick)
}, [])
// mousedown, not click — click fires after the element may have
// already been removed from the DOM.

Handlers and Keyboard Access

What an event handler owes a keyboard user, which is where most accessibility failures start.

Use a button, and disable during submission
// A div with onClick is invisible to a keyboard
<div onClick={select}>Select</div>                 // unreachable

<button onClick={select}>Select</button>           // just works

// If a non-button truly must be interactive, it needs all of this
<div role="button" tabIndex={0} onClick={select}
     onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && select()}>

// Async handlers — disable while in flight, or a double-click
// submits twice
async function handleSubmit(e) {
  e.preventDefault()
  setSubmitting(true)
  try { await save(values) }
  finally { setSubmitting(false) }
}
<button disabled={submitting}>{submitting ? 'Saving…' : 'Save'}</button>

Key Points to Remember

  • 1Event props take a function reference; adding parentheses calls it during render
  • 2Wrap in an arrow function to pass arguments — inline handlers are rarely a real performance problem
  • 3React attaches one listener per event type at the root and hands you a normalised SyntheticEvent
  • 4A document listener you add yourself fires before React handlers — use mousedown for click-outside
  • 5A clickable div is unreachable by keyboard; use a button, and disable it while a submit is in flight

Interview Questions

Sign in to ask Aria
1

What happens if you write onClick={handleClick()} instead of onClick={handleClick}?

Easy
2

How does React attach event listeners, and why does that design help?

Medium
3

Why does click-outside logic usually listen for mousedown rather than click?

Hard

Ask Aria about Handling Events

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…