← Back to Tutorials Chapter 4

Handling Events in React

Event Handling in React

Event handling in React is similar to handling events in the DOM, but with a few key differences. React events are named using camelCase (onClick instead of onclick), and you pass a function as the event handler rather than a string. React uses its own synthetic event system to ensure cross-browser compatibility.

// Basic event handling
function ClickButton() {
  const handleClick = () => {
    alert('Button clicked!');
  };

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

Common Event Types

// Multiple event handlers
function InputExample() {
  const [value, setValue] = useState('');

  const handleChange = (e) => setValue(e.target.value);
  const handleFocus = () => console.log('Focused');
  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      alert(`Submitted: ${value}`);
    }
  };

  return (
    <input
      type="text"
      value={value}
      onChange={handleChange}
      onFocus={handleFocus}
      onKeyDown={handleKeyDown}
    />
  );
}

Synthetic Events

React wraps native browser events into a SyntheticEvent object that provides a consistent interface across all browsers. The SyntheticEvent has the same properties as native events, including bubbles, cancelable, currentTarget, defaultPrevented, eventPhase, isTrusted, nativeEvent, preventDefault(), stopPropagation(), target, timeStamp, and type.

Performance Note: React's synthetic events are pooled for performance. This means the event object is reused and its properties are nullified after the event handler has finished executing. If you need to access an event property asynchronously (e.g., inside a setTimeout), you must call e.persist() to remove the event from the pool.
// Synthetic event object
function Form() {
  const handleSubmit = (e) => {
    e.preventDefault(); // Prevent page reload
    console.log('Form submitted');
    console.log('Target:', e.target);
    console.log('Type:', e.type);
  };

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

Passing Arguments to Event Handlers

When you need to pass additional arguments to an event handler, you can use an arrow function or the bind method. Arrow functions are the more common and readable approach in modern React.

// Using arrow function (recommended)
function ItemList({ items }) {
  const handleItemClick = (id, name) => {
    console.log(`Clicked item ${id}: ${name}`);
  };

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

Practical Examples

Click Counter

function ClickCounter() {
  const [count, setCount] = useState(0);

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

Toggle Button

function ToggleButton() {
  const [isOn, setIsOn] = useState(false);

  return (
    <button
      onClick={() => setIsOn(prev => !prev)}
      style={{ background: isOn ? '#22c55e' : '#ef4444' }}
    >
      {isOn ? 'ON' : 'OFF'}
    </button>
  );
}

Input Change Handler

function SignupForm() {
  const [formData, setFormData] = useState({
    username: '',
    email: '',
    password: '',
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({ ...prev, [name]: value }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form data:', formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="username" value={formData.username} onChange={handleChange} placeholder="Username" />
      <input name="email" type="email" value={formData.email} onChange={handleChange} placeholder="Email" />
      <input name="password" type="password" value={formData.password} onChange={handleChange} placeholder="Password" />
      <button type="submit">Sign Up</button>
    </form>
  );
}
React event handling diagram

Event-Aware Components Pattern

A common pattern in React is to create components that accept event handlers as props. This allows the parent component to control what happens when events occur, making the child component reusable in different contexts.

function ActionButton({ label, onAction, disabled }) {
  return (
    <button onClick={onAction} disabled={disabled}>
      {label}
    </button>
  );
}

// Usage
<ActionButton label="Save" onAction={handleSave} disabled={isSaving} />
<ActionButton label="Delete" onAction={handleDelete} disabled={false} />

Practice Task

Create a ColorPicker component that displays three buttons (Red, Green, Blue). When a button is clicked, the background color of a preview box changes to the corresponding color. Use the onClick event handler and pass arguments to identify which color was clicked. Also add a reset button that changes the background back to white.