Same logic, many screens
A momo shop app lets people pick toppings, select orders to print, and tick dishes to compare. Three screens, one piece of logic: a set of selected ids you can toggle and clear. Copy it three times and you will fix the same bug three times. React has had three answers to "how do I share stateful logic?" over the years, and big codebases contain all three — so you need to read them all, and know which to write today.
The Learning Patterns book walks through the history: higher-order components (HOCs) came first, then render props, and since React 16.8 custom hooks, which replace most uses of the other two. Today you'll write the same logic all three ways and see why hooks won.
Write it once, as a hook
A custom hook is just a function whose name starts with use and that calls other hooks. Each component that calls it gets its own state — hooks share logic, not data. Return an object so callers can pick what they need by name.
function useSelection(initial = []) {
const [selected, setSelected] = useState(initial);
const isSelected = (id) => selected.includes(id);
const toggle = (id) =>
setSelected((list) => list.includes(id) ? list.filter((x) => x !== id) : [...list, id]);
const clear = () => setSelected([]);
return { selected, isSelected, toggle, clear };
}The rules of hooks still apply: call hooks at the top level of a component or another hook — never inside conditions, loops or event handlers — so React can match each call to its state by order.