Summary
React viewport tracking has mutation-scaling and stale-state problems in dynamic/virtualized UIs.
Evidence
packages/react/src/useAskableViewport.ts:
- Relevant additions call
observeAll(), rescanning every annotation. Sequential inserts become approximately O(existing annotations × mutations).
- When an annotated parent is removed, cleanup processes the parent or descendants, not both. Annotated descendants can remain in the visible map.
- Changing only
scope updates a ref but does not flush output, leaving stale visibleItems until another observer callback.
Proposed fix
- Observe only each added node plus annotated descendants.
- On removal, process both an annotated root and every annotated descendant.
- Flush immediately on scope changes or derive filtered output from unfiltered state.
- Consider sharing core viewport machinery to avoid duplicate implementations.
Acceptance criteria
Summary
React viewport tracking has mutation-scaling and stale-state problems in dynamic/virtualized UIs.
Evidence
packages/react/src/useAskableViewport.ts:observeAll(), rescanning every annotation. Sequential inserts become approximately O(existing annotations × mutations).scopeupdates a ref but does not flush output, leaving stalevisibleItemsuntil another observer callback.Proposed fix
Acceptance criteria