Microtask deferral in SingleObserver causes ResizeObserver loop error — now reported by error trackers since Chrome 132
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 76/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Tranquilla
- Stack tecnologico
- react, typescript
- Ambito
- frontend
Direzione di ricerca
Leggi src/SingleObserver/index.tsx#L84-L87 e riproduci il problema con il CodeSandbox collegato, concentrandoti su come il callback scheduling influisce sui cambiamenti ripetuti delle dimensioni. Il lavoro è completato quando il resize callback non mantiene più il loop all’interno di un frame e la riproduzione non emette più il ResizeObserver error segnalato.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Environment
| Package | Version |
|---|---|
| rc-resize-observer | 1.4.3 |
| React | 19 |
| Browsers | Chrome/Edge 132+ (all Chromium-based) |
Description
SingleObserver defers its onResize callback via a microtask at src/SingleObserver/index.tsx#L84-L87:
// defer the callback but not defer to next frame
Promise.resolve().then(function () {
onResize(sizeInfo, target);
});
Microtasks execute within the same animation frame. When the deferred callback triggers a DOM layout change, the ResizeObserver fires again — creating a loop that exceeds the browser's depth limit. The browser then fires an ErrorEvent on window:
ResizeObserver loop completed with undelivered notifications.
Why this is now urgent — Chrome 132 change
This error has always occurred, but was previously invisible to error-tracking tools. Starting in Chrome 132, the ErrorEvent.error property changed from null to a string containing the error message (Chromium #391393420, chromium-dev thread).
| Before Chrome 132 | Chrome 132+ | |
|---|---|---|
ErrorEvent.error |
null |
"ResizeObserver loop completed..." |
| Error trackers | Silently discard | Capture as unhandled error |
Applications using rc-resize-observer (via antd Table, Typography, etc.) now see a large spike in error reports. Other projects have been affected by the same Chrome change: Odoo PR #196740.
Reproduction
CodeSandbox: https://codesandbox.io/p/sandbox/reproduction-rc-resize-observer-loop-error-t4crpg
import React, { useRef } from "react";
import RcResizeObserver from "rc-resize-observer";
const LoopTrigger = ({ index }: { index: number }) => {
const ref = useRef<null | HTMLDivElement>(null);
return (
<RcResizeObserver
onResize={() => {
if (ref.current) {
const current = ref.current.offsetHeight;
ref.current.style.height = (current <= 20 ? 21 : 20) + "px";
}
}}
>
<div ref={ref}>Element {index}</div>
</RcResizeObserver>
);
};
export default function App() {
return (
<div>
{Array.from({ length: 10 }, (_, i) => (
<LoopTrigger key={i} index={i} />
))}
</div>
);
}
Each LoopTrigger wraps an element in <RcResizeObserver>. The onResize callback mutates the element's height, triggering another observation. Because rc-resize-observer delivers the callback via Promise.resolve().then(), the loop stays within the same frame. Open the codesandbox preview console — the error appears immediately on load.
Root cause
- Browser layout phase detects size change
- Singleton
ResizeObserverfires →observerUtil.jsdispatches to listeners SingleObserver.onInternalResizedefers viaPromise.resolve().then()— still same frame- Microtask fires
onResize→ layout change → browser detects new size change → loop - Exceeds depth limit →
ErrorEventwith.errorpopulated (Chrome 132+) → error trackers capture it
Suggested fix
Replace the microtask deferral with requestAnimationFrame to break the loop across frame boundaries:
// Let collection know what happened
onCollectionResize?.(sizeInfo, target, data);
if (onResize) {
- // defer the callback but not defer to next frame
- Promise.resolve().then(function () {
- onResize(sizeInfo, target);
- });
+ // defer the callback to the next frame to break the ResizeObserver loop
+ requestAnimationFrame(function () {
+ onResize(sizeInfo, target);
+ });
}
The comment in the existing code ("defer the callback but not defer to next frame") shows the microtask was intentional, but requestAnimationFrame would break the loop by deferring to the next frame — after the browser has finished processing all pending resize observations.
Related issues
- #33
- ant-design/ant-design#26621
- ant-design/ant-design#47159
- Chromium #391393420 — ErrorEvent.error change
- chromium-dev thread — ResizeObserver errors in Chrome >=132
- Odoo PR #196740 — catch ResizeObserver error in Chrome 132
- Lingua principale
- JavaScript
- Stelle
- 201
- Fork
- 47
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di react-component/resize-observer
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
-
findDOMNode is deprecated Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
react-component/resize-observer#208 · 8 commenti · 28 reazioni ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 20/100
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
react-component/resize-observer#190 · 1 commento ·
-
文本节点通过observe监听报类型错误 Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
Tutte le issue di react-component/resize-observer
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
HarperFast/skills#96 ·
-
[Block] Latest Posts [Type] Bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
-
Daemon passes --experimental-wasm-jspi unconditionally on Node >= 24; Node 26 rejects the flag Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
Automattic/studio#4908 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
sugarlabs/musicblocks#8847 ·