React Pointer Hooks: Hover, Long-Press, Double-Click, Scratch, and Click-Outside Without the Bugs
Pointer events are the part of React nobody writes about because everybody assumes they have already been figured out. They have not. The standard answers — onMouseEnter, onClick, a setTimeout for double-click, a window listener for click-outside — all work in the demo and all break in production. They flicker as the cursor crosses a child element. They fire an iOS ghost click 300 ms after a touch ends. They miss elements rendered through a portal. They count a double-click as two single-clicks because the second click handler runs before the first one is cancelled.
The DOM event model is what it is. Browsers ship different gesture pipelines on mobile and desktop, the spec for dblclick is older than React, and composedPath() is the only reliable way to walk a click out through shadow boundaries and portals. None of that is going to change. What you can change is whether every component in your app re-implements the workarounds from scratch.
ReactUse ships six small pointer hooks that close the gaps. This post walks each one: the bug in the naive version, what the hook does instead, and a concrete component you would actually build with it. If you read the post on the ref escape hatch, one detail will look familiar — most of these hooks use useLatest internally so that the listener stays stable even as the callback identity moves.






