liveBook · Manning

Event handler generator

As explained in React Quickly, Second Edition

An event handler generator is a function that returns an event handler when invoked with configuration or event-specific arguments.

An event handler generator is a function that returns an event handler when invoked with configuration or event-specific arguments. It reduces duplicated handlers that differ only in a value such as a counter delta or form-field key. section 8.7 section 9.2.3

Use the pattern to:

  • Create counter handlers from one updater: `update = (delta) => () => setCounter(...)`, then pass `update(1)` or `update(-1)` to buttons. section 8.7
  • Update many form fields through one handler: `onChange = (key) => (evt) => ...`, using the key to select the state property. section 9.2.3
  • Simplify forms further by reading each input’s `name` from `evt.target`, allowing every field to share one `onChange` handler. section 9.2.3

Address form

Store address fields in one state object and preserve the other values while updating one key: `setData(oldData => ({ ...oldData, [key]: evt.target.value }))`. Each input can receive `onChange={onChange(key)}`; the simpler alternative uses `name="city"` and a shared `onChange`. section 9.2.3

function Counter() {
  const [counter, setCounter] = useState(0);
  const update = (delta) => () =>                       #1
    setCounter((c) => c + delta);                       #1
  return (
    <>
      <h1>Value: {counter}</h1>
      <button onClick={update(1)}>Increment</button>    #2
      <button onClick={update(-1)}>Decrement</button>   #2
    </>
  );
}

Compare the generated counter handlers with the more verbose inline handlers to see how invocation supplies the event-specific delta. section 8.7

Listing 9.4 Address form
import { useState } from "react";
function Address() {
  const [data, setData] = useState({              #1
    address1: "",                                 #1
    address2: "",                                 #1
    zip: "",                                      #1
    city: "",                                     #1
    state: "",                                    #1
    country: "",                                  #1
  });                                             #1
  const onChange = (key) => (evt) => {            #2
    setData((oldData) =>                          #3
      ({ ...oldData, [key]: evt.target.value })   #3
    );                                            #3
  };
  return (
    <form style={{ display: "flex", flexDirection: "column" }}>
      <label>
        Address line 1:
        <input
          value={data.address1}                   #4
          onChange={onChange("address1")}         #4
        />
      </label>
      <label>
        Address line 2:
        <input
          value={data.address2}                   #4
          onChange={onChange("address2")}         #4
        />
      </label>
      <label>
        Zip:
        <input
          value={data.zip}                        #4
          onChange={onChange("zip")}              #4
        />
      </label>
      <label>
        City:
        <input
          value={data.city}                       #4
          onChange={onChange("city")}             #4
        />
      </label>
      <label>
        State:
        <input
          value={data.state}                      #4
          onChange={onChange("state")}            #4
        />
      </label>
      <label>
        Country:
        <input
          value={data.country}                    #4
          onChange={onChange("country")}          #4
        />
      </label>
    </form>
  );
}
function App() {
  return <Address />;
}
export default App;

Inspect a complete address-form implementation using one state object and a handler generator for each field. section 9.2.3

How React Quickly, Second Edition covers it

How deep it goes
Explains the function-returning-function pattern with counter and form examples, but treats its logic as optional and somewhat esoteric.
Examples
Uses increment/decrement buttons, a multi-field address form, keyed updates, and inputs identified through the name property.
What it assumes
Assumes basic React state, JSX event props, and input events while introducing the function-returning-function technique.
What you can do after
Build it from scratch by generating counter and form handlers from deltas, keys, or input names.
How it connects
Connects event handler generators to React state, event handlers, forms, input events, and JSX.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React Quickly, Second Edition. The section links point to the parts of the book it draws on.