React Event Handling

Handle user interactions using synthetic events, inline handlers, parameter passing, and default prevention.

TL;DR

  1. Attach camelCase event handlers like onClick directly to JSX tags.
  2. Pass handler function references instead of invoking them inside JSX markup.
  3. Prevent native browser reloads using the preventDefault event method.

Basic Event Handlers

    Named Function Handler

    Reference a declared handler function cleanly in JSX.

    export function Button() {
      function handleClick() {
        console.log('Button clicked!');
      }
      return (
        <ButtonBase onClick={handleClick}>
          Go
        </ButtonBase>
      );
    }
    Inline Arrow Handler

    Write concise one-line handlers directly in JSX attributes.

    <ButtonBase onClick={() => console.log('Clicked')}>
      Quick Action
    </ButtonBase>
    Passing Arguments

    Pass dynamic parameters using an arrow function wrapper.

    <ButtonBase onClick={() => removeUser(user.id)}>
      Delete User
    </ButtonBase>

Form and Input Events

    Form Submit Prevention

    Prevent page reload and process form payload in React.

    function handleSubmit(e: React.FormEvent) {
      e.preventDefault();
      // process submission
    }
    return <Form onSubmit={handleSubmit}>...</Form>;
    Input Change Event

    Read input value from target inside change handler.

    function handleChange(
      e: React.ChangeEvent<HTMLInputElement>
    ) {
      console.log(e.target.value);
    }
    return <InputBase onChange={handleChange} />;
    Keyboard Key Down

    Respond to specific key presses like Enter or Escape.

    function handleKeyDown(e: React.KeyboardEvent) {
      if (e.key === 'Enter') submitSearch();
    }
    return <InputBase onKeyDown={handleKeyDown} />;

Event Propagation

    Stop Propagation

    Prevent event from bubbling up to parent containers.

    function handleChildClick(e: React.MouseEvent) {
      e.stopPropagation();
      doChildAction();
    }
    Capture Phase Events

    Intercept events during the capture phase using Capture suffix.

    <Card onClickCapture={() => console.log('Capture')}>
      <ButtonBase>Click</ButtonBase>
    </Card>
    Synthetic Event Pooling

    In modern React, event objects persist across async calls.

    async function handleAsyncClick(e: React.MouseEvent) {
      const tag = e.currentTarget.tagName;
      await fetch('/api/log');
      console.log('Clicked:', tag);
    }

Pointer and Focus Events

    Hover State Triggers

    Track mouse entry and exit with pointer events.

    <CardView
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
    />
    Focus and Blur

    Handle element focus and loss of focus cleanly.

    <InputBase
      onFocus={() => setShowHints(true)}
      onBlur={() => setShowHints(false)}
    />
    Wheel Scroll Handler

    Capture user mouse wheel movement events.

    <CardView onWheel={(e) => console.log(e.deltaY)} />

Tips

  1. Pass a function reference like onClick={handleClick} rather than invoking it immediately with parenthesis inside the JSX template.
  2. Use TypeScript React.MouseEvent or React.ChangeEvent types to gain complete autocompletion and safety on event target elements.

Warnings

  1. Writing onClick={handleClick()} invokes your handler on initial render, causing unwanted infinite re-render loops in stateful components.
  2. Remember that React synthetic events bubble up the component hierarchy unless explicitly intercepted with the stopPropagation method.

In Practice

FAQ