Custom Hooks Reuse Stateful Logic, Not State Itself
Custom Hooks are React's primary mechanism for composing stateful logic, but two misunderstandings trip up developers repeatedly: assuming shared logic means shared state, and treating StrictMode's double-fire as a framework defect rather than a cleanup audit. Getting the subscription-cleanup symmetry right prevents memory leaks and duplicate listeners that degrade performance in real applications.
A React component that tracks mouse coordinates with `useState` and `useEffect` mixes state management, browser event subscription, and UI rendering. Moving that logic into a custom `useMouse` Hook isolates the lifecycle-aware conversion of browser events into React state. The Hook returns only the coordinates; the component decides how to display them.
Several subtle pitfalls surface along the way. Checking `x && y` for a "mouse moved" condition breaks when coordinates are zero because JavaScript treats `0` as falsy; the correct check is `x !== null && y !== null`. Cleanup functions must reference the same function object passed to `addEventListener`, and React StrictMode's double-mount in development is a deliberate check for missing cleanup, not a bug.
Calling the same custom Hook from multiple components reuses the logic but creates independent state and effect instances. Sharing a single mouse position across components requires lifting the Hook call higher and distributing the result via props or Context.
The `x && y` falsy-coercion bug is a concrete example of why conditional rendering should express business semantics (`hasMoved`) rather than lean on JavaScript truthiness.
StrictMode's double-mount behavior is widely misunderstood as a bug; framing it as React verifying cleanup symmetry makes the design intention clearer.
The distinction between custom Hooks (reuse logic), Context (share data), and plain functions (reuse computation) gives developers a precise vocabulary for deciding where code belongs.