Skip to content

useAnchoredPosition: skip re-renders when the overlay position is unchanged #8713

Open

Description

@mattcosta7

Part of #8676 (P0).

Problem

An open anchored overlay re-renders even when its position hasn't changed. This affects every open ActionMenu, SelectPanel, Autocomplete and AnchoredOverlay.

  • hooks/useAnchoredPosition.ts:91-106: the setPosition updater always returns a new object, so React never bails out.
  • hooks/useAnchoredPosition.ts:142: the window-size observer calls useResizeObserver with no target, which observes document.documentElement. Any page height change then triggers a position update, including content loading below the anchor.

Measured: an open AnchoredOverlay committed 2 times across 5 document height changes below the anchor, with the position unchanged. The control, with no page change, committed 0 times in 300 ms. That was React 18.3.1 in headless Chromium.

Proposed fix

  • Return prev from the setPosition updater when top, left and anchorSide are unchanged.
  • Listen to window resize for viewport changes instead of observing document.documentElement, as PageLayout/usePaneWidth.ts already does. Keep the useResizeObserver on the floating element.
  • Check the stale settings dependency. updatePosition reads settings, but the deps array at :115 leaves it out, so changing side or align while the overlay is open may not reposition it. This was read from code and not reproduced, so confirm it before changing behavior.

The fix must work on React 18 and 19.

Acceptance criteria

  • A regression test with an open overlay changes the document height several times without moving the anchor, and asserts that the overlay doesn't commit again.
  • Resizing the viewport still repositions the overlay.
  • A change in the floating element's size still repositions it.
  • onPositionChange behavior doesn't change.
  • The settings dependency question is resolved: fixed with a test, or shown to be a non-issue.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions