Skip to content

fix(useElementByPoint): avoid a re-render on every frame in multiple mode - #210

Closed
ostapondo wants to merge 1 commit into
childrentime:mainfrom
ostapondo:fix/element-by-point-frame-rerender
Closed

fix(useElementByPoint): avoid a re-render on every frame in multiple mode#210
ostapondo wants to merge 1 commit into
childrentime:mainfrom
ostapondo:fix/element-by-point-frame-rerender

Conversation

@ostapondo

Copy link
Copy Markdown
Contributor

Description

With multiple: true, useElementByPoint re-renders the consuming component on
every animation frame, even when the pointer hasn't moved and the elements under
it haven't changed.

elementsFromPoint() returns a freshly allocated array on each call, so the rAF
loop hands setElement a new reference every frame. React compares by identity,
sees a change, and re-renders — roughly 60 times a second, for as long as the
hook is active. The single-element path doesn't have this problem, since
elementFromPoint() returns the same node and React bails out on its own.

The fix compares the hit list by contents and keeps the previous array when
nothing changed. I used the functional form of setElement so the comparison
sees the committed value without needing an extra ref.

Type of Change

  • Bug fix
  • New hook
  • Enhancement to existing hook
  • Documentation update
  • Other (please describe)

Checklist

  • I have read the Contributing Guide
  • My code follows the project's coding style
  • I have added tests for my changes
  • All existing tests pass
  • I have updated the documentation

No doc change — public API and return values are unchanged.

This hook had no spec file, so I added one. Three tests: the element is reported
for the single case, an unchanged hit list no longer re-renders (3 renders over 3
frames on main, 0 here), and a hit list that genuinely changes still updates —
that last one matters, since a comparison like this is exactly the kind of change
that can silently freeze state.

@ostapondo
ostapondo force-pushed the fix/element-by-point-frame-rerender branch 2 times, most recently from 5b82365 to f0f9d7e Compare July 29, 2026 13:49
…mode

elementsFromPoint() allocates a new array on every call, so the rAF loop
handed setElement a fresh reference each frame and re-rendered the
consuming component roughly 60 times a second even while the pointer sat
still. Compare the hit list by contents and keep the previous array when
nothing under the point changed. The single-element branch needs no such
check - elementFromPoint returns the same node and React bails out on
its own.

Adds the first tests for this hook, covering both that an unchanged hit
list does not re-render and that a changed one still does.
@ostapondo
ostapondo force-pushed the fix/element-by-point-frame-rerender branch from f0f9d7e to b7278e5 Compare July 29, 2026 13:51
@ostapondo ostapondo closed this by deleting the head repository Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant