react-component / react-component/resize-observer

Support ResizeObserverEntry-based measurement to avoid forced layout reads

Open
#242 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
201
Forks
47
PR merge metrics
No merged PRs in 30d

Description

Context

@rc-component/resize-observer currently calls target.getBoundingClientRect() for every observed target in useResizeObserver, then reads offsetWidth and offsetHeight:

https://github.com/react-component/resize-observer/blob/master/src/useResizeObserver.ts

For consumers that observe many elements, these per-target synchronous layout reads can become a significant mount cost. A concrete example is @rc-component/table: a fixed-header table observes one hidden measure cell per column. The report in react-component/table#1507 measured 86 getBoundingClientRect calls and about 547 ms of forced-layout self-time for a roughly 40-column cold mount under 4x CPU throttling.

ResizeObserver.Collection batches the resulting callbacks, but the size of each target has already been read through getBoundingClientRect() before the collection receives it.

Proposal

Would an opt-in measurement mode based on the native ResizeObserverEntry be acceptable?

The intended behavior would be:

  • use entry.borderBoxSize when it is available;
  • fall back to offsetWidth and offsetHeight where necessary;
  • avoid getBoundingClientRect() in this mode;
  • preserve the existing measurement behavior by default, including its current transform and fractional-size semantics;
  • keep the existing SizeInfo, onResize, and ResizeObserver.Collection contracts usable.

The exact public API name is intentionally left open for maintainer guidance. Possible shapes could be a measurement strategy option or a narrowly scoped flag on ResizeObserver / useResizeObserver.

Motivation for implementing this here

Handling this in @rc-component/resize-observer would let consumers such as Table keep using the shared observer and collection abstraction instead of creating their own native ResizeObserver implementation solely to avoid the forced layout reads.

If this direction is acceptable, I can send a PR with tests covering:

  • no getBoundingClientRect() call in the opt-in mode;
  • fractional borderBoxSize values;
  • the offsetWidth / offsetHeight fallback;
  • unchanged default behavior;
  • batched ResizeObserver.Collection notifications.
Related
  • react-component/table#1507
  • react-component/resize-observer#236 is about callback scheduling and ResizeObserver loop errors; this proposal is only about the size measurement source.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/useResizeObserver.ts and trace how measurements reach SizeInfo, onResize, and ResizeObserver.Collection. Review the existing measurement behavior before proposing the opt-in API. Done means the opt-in path uses ResizeObserverEntry borderBoxSize or offset dimensions without getBoundingClientRect(), while default behavior and collection notifications remain unchanged; add tests for the listed cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.