Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 14
Beginner

React Event Handling

Handle user events in React with camelCase handlers, synthetic events, and controlled inputs.

TL;DR

  1. 01Use camelCase event names like onClick and onChange in JSX.
  2. 02Pass a function reference as the handler, not a function call.
  3. 03Use e.preventDefault() and e.stopPropagation() to control event flow.

Tips

  1. 01Always use controlled components for forms — it gives you better control over input values and validation.

Warnings

  1. 01Remember to call preventDefault() on forms to prevent page reload on submission.
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 15
Beginner

React Event Handling

(continued)

Basic Event Handlers

  • Attach events with camelCase attribute names like onClick, not lowercase onclick.
    function Button() {
      function handleClick() {
        console.log("Button clicked");
      }
    
      return <button onClick={handleClick}>Click me</button>;
    }
    
  • Pass a function reference, not a function call, or it runs on every render.
    // Good: pass the function
    <button onClick={handleClick}>Click</button>
    
    // Bad: calls function immediately on render
    <button onClick={handleClick()}>Click</button>
    
  • Write inline handlers as arrow functions for short, one-off logic.
    <button onClick={() => console.log("clicked")}>Click</button>
    
  • Pass extra arguments to a handler by wrapping the call in an arrow function.
    function List({ items }) {
      return (
        <ul>
          {items.map(item => (
            <li key={item.id}>
              <button onClick={() => handleDelete(item.id)}>
                Delete {item.name}
              </button>
            </li>
          ))}
        </ul>
      );
    }
    
  • Name handler functions with a handle prefix so their purpose is obvious at a glance.
    function handleDelete(id) { /* ... */ }
    function handleToggle() { /* ... */ }
    
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 16
Beginner

React Event Handling

(continued)

Common Event Handlers

  • Handle form submission with onSubmit on the <form> element, not onClick on the button.
    function LoginForm() {
      const handleSubmit = (e) => {
        e.preventDefault();
        console.log("Form submitted");
      };
    
      return <form onSubmit={handleSubmit}></form>;
    }
    
  • Handle input changes with onChange, reading the new value from e.target.value.
    function NameInput() {
      const [name, setName] = useState("");
    
      return <input value={name} onChange={(e) => setName(e.target.value)} />;
    }
    
  • Handle mouse events like onMouseEnter, onMouseLeave, and onMouseMove for hover effects.
    <div onMouseEnter={() => setHovered(true)}>
      Hover me
    </div>
    
  • Handle keyboard shortcuts with onKeyDown, checking e.key for the pressed key.
    function SearchBox() {
      const handleKeyDown = (e) => {
        if (e.key === "Enter") submitSearch();
        if (e.key === "Escape") clearSearch();
      };
    
      return <input onKeyDown={handleKeyDown} placeholder="Search..." />;
    }
    
  • Handle focus and blur events with onFocus and onBlur for accessibility cues.
    function Input() {
      const [focused, setFocused] = useState(false);
    
      return (
        <input
          className={focused ? "focused" : ""}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
        />
      );
    }
    
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 17
Beginner

React Event Handling

(continued)

Event Object

  • Access event properties like target and preventDefault.
    function handleClick(event) {
      console.log(event.target);  // the element clicked
      console.log(event.type);    // "click"
    }
    
    function handleSubmit(event) {
      event.preventDefault();     // stop form submission
      event.stopPropagation();    // stop event bubbling
    }
  • React's SyntheticEvent wraps the browser's native event for cross-browser consistency; access the underlying event with e.nativeEvent.
    function handleClick(e) {
      console.log(e.nativeEvent); // the underlying browser Event
    }
  • As of React 17, synthetic events are no longer pooled and reused: each event object is freshly created and stays valid for as long as you hold a reference to it, even after the handler returns. Calling e.persist() is now a no-op kept only for backward compatibility — you never need to call it.
    // React 16 and earlier nulled out event fields after the handler ran,
    // so reading e.target.value async required e.persist() first.
    // React 17+: the event object is never pooled, so this just works.
    function handleChange(e) {
      setTimeout(() => console.log(e.target.value), 1000);
    }
  • Get input values with e.target.value.
    const handleChange = (e) => {
      setName(e.target.value);
    };
  • Read checkbox state with e.target.checked.
    function Checkbox() {
      const [checked, setChecked] = useState(false);
      
      return (
        <input
          type="checkbox"
          checked={checked}
          onChange={(e) => setChecked(e.target.checked)}
        />
      );
    }
  • Get the key pressed from keyboard events with e.key.
    function handleKeyDown(e) {
      console.log(e.key);    // "Enter", "Escape", "ArrowUp"
      console.log(e.code);   // "Enter", "Escape", "ArrowUp"
      console.log(e.ctrlKey); // true if Ctrl held
    }
  • Access the current target when events bubble up.
    function handleClick(e) {
      console.log(e.target);        // element that was clicked
      console.log(e.currentTarget); // element with the handler
    }
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 18
Beginner

React Event Handling

(continued)

Controlled vs Uncontrolled Components

  • Controlled components: React manages the input value.
    function TextInput() {
      const [value, setValue] = useState("");
      
      return (
        <input 
          value={value}
          onChange={(e) => setValue(e.target.value)}
        />
      );
    }
  • Uncontrolled components: DOM manages the input.
    function TextInput() {
      const inputRef = useRef();
      
      function handleSubmit() {
        console.log(inputRef.current.value);
      }
      
      return (
        <>
          <input ref={inputRef} />
          <button onClick={handleSubmit}>Submit</button>
        </>
      );
    }
  • Use defaultValue for uncontrolled inputs with an initial value.
    // defaultValue sets the initial value but doesn't control updates
    <input defaultValue="Alice" ref={inputRef} />
  • Controlled inputs enable real-time validation and formatting.
    function PhoneInput() {
      const [phone, setPhone] = useState("");
      
      const handleChange = (e) => {
        // Format as user types: 555-123-4567
        const digits = e.target.value.replace(/\D/g, "");
        setPhone(digits.replace(/(\d{3})(\d{3})(\d{4})/, "$1-$2-$3"));
      };
      
      return <input value={phone} onChange={handleChange} />;
    }
  • Prefer controlled components for forms that need validation.
    // Controlled: easy to read and validate before submit
    const isValid = email.includes("@") && password.length >= 8;
    <button disabled={!isValid}>Submit</button>
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 19
Beginner

React Event Handling

(continued)

Event Delegation

  • Use event delegation for lists of items.
    function List({ items }) {
      const handleItemClick = (e) => {
        if (e.target.dataset.id) {
          console.log("Item clicked:", e.target.dataset.id);
        }
      };
      
      return (
        <ul onClick={handleItemClick}>
          {items.map(item => (
            <li key={item.id} data-id={item.id}>
              {item.name}
            </li>
          ))}
        </ul>
      );
    }
  • More efficient than adding listeners to each item.
  • Use data-* attributes to identify clicked elements.
  • Use e.target.closest() to find the nearest matching ancestor.
    function handleClick(e) {
      const row = e.target.closest("[data-row-id]");
      if (row) {
        console.log("Row clicked:", row.dataset.rowId);
      }
    }
  • Stop bubbling with e.stopPropagation() to prevent parent handlers.
    function Card() {
      return (
        <div onClick={handleCardClick}>
          Card content
          <button onClick={(e) => {
            e.stopPropagation(); // don't trigger handleCardClick
            handleDeleteClick();
          }}>
            Delete
          </button>
        </div>
      );
    }
Notes
Useful Cheatsheetsusefulcheatsheets.com
React Event Handling
Chapter 02 · Page 20
Beginner

React Event Handling

(FAQ)

FAQ

You're likely calling the function instead of passing a reference — write onClick={handleClick} not onClick={handleClick()}. If you need to pass arguments, wrap it in an arrow function: onClick={() => handleClick(id)}.

Use e.target.value inside your handler function, e.g. onChange={(e) => setValue(e.target.value)}. For checkboxes, use e.target.checked instead.

preventDefault stops the browser's default behavior (like a form submitting or a link navigating), while stopPropagation stops the event from bubbling up to parent elements. You often need both independently depending on what you're trying to block.

Uncontrolled components (using ref) are useful for file inputs or when integrating with non-React code, since file inputs can't be controlled by React state. For most form fields, controlled components give you real-time access to values for validation and conditional logic.

Add a name attribute to each input and use e.target.name in one handler to update the correct state key: setState(prev => ({ ...prev, [e.target.name]: e.target.value })). This avoids writing a separate handler for every field.