I'm seeing the following error when I dismiss a particular modal:
This didn't happen when I was using react-router v5, but I've recently updated to v6 due to other requirements and it started happening. Funny thing is, I have a second page that invokes the same dialog and it doesn't trigger the error.
(Note that this is a development environment, not a production build. It might not appear in production, or just go to the console.)
I can't seem to find anything through googling... the closest I get are references to "ResizeObserver - loop limit exceeded". I'm puzzled by this, since it doesn't occur on the other page. To make matters worse, the application is using v3 of Bootstrap (company legacy reasons, I don't have the bandwidth right now to address that).
Any ideas?
I'm seeing the following error when I dismiss a particular modal:
This didn't happen when I was using react-router v5, but I've recently updated to v6 due to other requirements and it started happening. Funny thing is, I have a second page that invokes the same dialog and it doesn't trigger the error.
(Note that this is a development environment, not a production build. It might not appear in production, or just go to the console.)
I can't seem to find anything through googling... the closest I get are references to "ResizeObserver - loop limit exceeded". I'm puzzled by this, since it doesn't occur on the other page. To make matters worse, the application is using v3 of Bootstrap (company legacy reasons, I don't have the bandwidth right now to address that).
Any ideas?
Share Improve this question edited Jan 27 at 12:12 marekful 15.4k6 gold badges38 silver badges63 bronze badges asked May 6, 2023 at 5:19 rjrayrjray 6,6634 gold badges36 silver badges37 bronze badges 4 |20 Answers
Reset to default 63The dialog in question was rendering a form, and by removing one element at a time I was able to determine that one specific text-entry field was causing the issue.
The problem stemmed from the LastPass browser extension trying to provide the option of auto-fill for that field. If I shortened the width of the field, it no longer caused the error. If I disabled the LP auto-fill icon from appearing, it also solved the issue. I chose the latter, since this was not something that LP could really auto-fill anyway.
I don't know why this only triggered when I upgraded from v5 to v6 of react-router-dom
. Our staging and production instances that have not yet received the upgraded code work fine with the LP icon present in the field. Nonetheless, the issue is fixed for me.
I've stumbled upon a similar problem, though not quite related to react-router per se.
The specs say that this happens in case of infinite resize loops as it's displayed here.
To prevent this from happening, we've figured out using a cunning mediator function, which utilizes window.requestAnimationFrame()
to render things properly.
Typescript code:
const observerCallback: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
window.requestAnimationFrame((): void | undefined => {
if (!Array.isArray(entries) || !entries.length) {
return;
}
yourResizeHandler();
});
};
const resizeObserver = new ResizeObserver(observerCallback);
If you aren't using ResizeObserver
in your code, you shouldn't worry about it, it will not appear in build version of your app.
If you are using ResizeObserver
check this to get a better understanding of the causes of the error Observation Errors:
Implementations following the specification invoke resize events before paint (that is, before the frame is presented to the user). If there was any resize event, style and layout are re-evaluated — which in turn may trigger more resize events. Infinite loops from cyclic dependencies are addressed by only processing elements deeper in the DOM during each iteration. Resize events that don't meet that condition are deferred to the next paint
This basically means the event of resize happens before the paint and if you do a resize to something that causes another event (before the paint) you could cause an infinite loop.
You can solve that by delaying "Your resize" so that it happens after the repaint, however if there are multiple resize events some of them will happen before the paint (caused by an old delayed resize).
You can avoid this by de-bouncing events and only doing a reaction to the last one (Cancel all your resizes until the observed element "settles").
Here an example on how to solve this in React
// Here we are trying to match the size of div to an observed div
// it will affect the origianl one if it is inside it or next to it...
const observedDivRef = useRef(null);
const resizingDelayTimer = useRef(null);
useEffect(() => {
const observer = new ResizeObserver(() => {
clearTimeout(resizingDelayTimer.current);
resizingDelayTimer.current = setTimeout(() => {
// check if the observed div is still mounted
// else this will cause memory leak
if (observedDivRef.current) {
setMatchingDivWidth(observedDivRef.current.clientWidth)
}
}, 100)
});
observer.observe(observedDivRef);
return () => {
if (observer && observedDivRef.current) observer.unobserve(observedDivRef.current);
}
}, []);
You can find an explanation for this exact error in the documentation
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver#observation_errors
So from my understanding, that error means that you have a case when the browser got so many resize events that it doesn't have a chance for an actual repaint, even though the layout has been changed. I fixed that problem by wrapping callback with debounce from Lodash with 0 timeout.
new ResizeOserver(debounce((entries) => {
for (const entry of entries) {
// enter code here
}
}))
For me the issue happens with Cascader from Ant design and only in webpack dev server. Sujen's solution works, but it is a kill switch from all the webpack errors. There is more elegant way to hide them optionally on the webpack side. Edit file webpack.config.js to hide runtimeErrors only:
module.exports = {
//...
devServer: {
client: {
overlay: {
runtimeErrors: false,
},
},
},
};
or even better - forward the error to the console:
module.exports = {
//...
devServer: {
client: {
overlay: {
runtimeErrors: (error) => {
if(error?.message === "ResizeObserver loop completed with undelivered notifications.")
{
console.error(error)
return false;
}
return true;
},
},
},
},
};
Add the below line to your main CSS file like app.css or app.scss
iframe#webpack-dev-server-client-overlay{display:none!important}
This hook solved my problem.
const useHideUnimportantErrors = () => {
useEffect(() => {
function hideError(e) {
if (e.message === 'ResizeObserver loop completed with undelivered notifications.') {
const resizeObserverErrDiv = document.getElementById(
'webpack-dev-server-client-overlay-div'
);
const resizeObserverErr = document.getElementById(
'webpack-dev-server-client-overlay'
);
if (resizeObserverErr) {
resizeObserverErr.setAttribute('style', 'display: none');
}
if (resizeObserverErrDiv) {
resizeObserverErrDiv.setAttribute('style', 'display: none');
}
}
}
window.addEventListener('error', hideError)
return () => {
window.addEventListener('error', hideError)
}
}, [])
}
I came across this thread as I also had the React: ResizeObserver loop completed with undelivered notifications error. I removed fullWidth and set my width to 99%, and that fixed my issue.
<TextField
sx={{
"& fieldset": { border: 'none' },
width: "99%"
}}
id="resultBox"
multiline
// fullWidth
variant="outlined"
value={resultsText}
inputRef={resultBoxRef}
>
</TextField>
I had encountered this issue, upon further investigation of my code it turned out that, even though, I had updated to the latest version of React, I hadn't refactored the JS in my App.js file.
I simply resolved by updating my App.js file to the below
const container = document.getElementById("root");
const root = createRoot(container!);
root.render(<App />);
In my case, I was using the TextField component from Material UI with the options minRows and maxRows. However, when the content changed, this caused the component and its parent components to resize. My solution was to remove the minRows and maxRows options and instead use the rows option exclusively.
FIXED in MUI (not hide)
Find the problem: The error doesnt give much information, go to the page that this error is happening, comment out different elements and find the broken one. I'm using Material UI and I found that multiline TextFields caused the problem. (it takes time)
Fix it: after tons of try and errors I could fix it by adding minHeight to my TextField, see the code I've added.
<TextField fullWidth label="label" name="name" multiline sx={{ "& textarea": { minHeight: "100px", }, }} />
I had this issue due to an expensive callback function and a few DOM changes happening in quick succession. Debouncing it fixed the problem.
useEffect(() => {
const observeTarget = ref.current;
if (!observeTarget) return;
const debouncedCallback = debounce((entry) => {
setElementSize({ width: entry.contentRect.width, height: entry.contentRect.height });
if (callback && typeof callback === 'function') {
callback(entry.contentRect);
}
}, debounceTime);
const resizeObserver = new ResizeObserver((entries) => {
if (!Array.isArray(entries) || !entries.length) return;
const entry = entries[0];
debouncedCallback(entry);
});
resizeObserver.observe(observeTarget);
return () => resizeObserver.unobserve(observeTarget);
}, [ref, callback, debounceTime]);
In my case, I just need to set the min-width for the body element in the "index.css" file.
body {
min-width: 400px;
}
I had the same issue using SyncFusion's RichTextEditor. Whenever I wrote enough characters so that the editor grew, and then deleted some lines, it resized and this error was fired.
Figured out it wasn't because of React or because of the component itself, but because I was using Firefox with the extension "LanguageTool", a grammar checker (thus observing textareas...).
If someone else is having the same issue, try using another navigator and maybe disable your plugins; one of them might be the culprit...
I was able to fix the ResizeObserver completed with undelivered notifications
error by writing local ResizeObserver hook (I'm using Typescript with React, react-router v6, react v17), the code is below.
I have a feeling that this error happens if calling ResizeObserver without checking for ref && ref.current.
In the hook, I return only the height
and width
of contentBoxSize
, but you can modify the return to your needs. I'm using ResizeObserver to dynamically adjust the size of the container with a pdf file in it (I didn't include the pdf-related code, only the hook and a parent component).
type ResizeObserverReturnType = {
height: number | undefined;
width: number | undefined;
}
// The ResizeObserver hook
export const useResizeObserver = (
ref: React.MutableRefObject<HTMLDivElement | null>
): ResizeObserverReturnType => {
const [height, setHeight] = useState<number | undefined>(undefined);
const [width, setWidth] = useState<number | undefined>(undefined);
const observer: ResizeObserver = useMemo(() => {
return new ResizeObserver(([entry]) => {
const height = entry.contentBoxSize[0].blockSize;
const width = entry.contentBoxSize[0].inlineSize;
setHeight(height);
setWidth(width);
});
}, []);
useEffect(() => {
if (ref && ref.current) {
observer.observe(ref.current);
}
// Remove the observer as soon as the component is unmounted
return () => {
observer.disconnect();
};
}, [observer, ref]);
return { height, width };
};
And then in my component I use this hook by providing a ref to it:
type Props = {
testValue: string;
};
export const YourContainer: React.FC<Props> = props => {
// Create ref
const ref = useRef<HTMLDivElement | null>(null);
// Pass ref to observer
const { height = 1, width = 1 } = useResizeObserver(ref);
// Connect ref to your container
return (
<StyledContainer ref={ref}>
{
// Render a component that is changing in size
// Pass required width and/or height
<YourComponent width={width} height={height} />
}
</StyledContainer>
);
};
I realized that LastPass, in its zeal to manage form inputs, was inadvertently intensifying the situation. Each dynamically generated form input was like a new battlefield for ResizeObserver and LastPass, creating a loop of updates that pushed ResizeObserver to its limits. One of the many temporary solution is to disable the LastPass extension from your browser. However, in my sitemaster.js file, I handled this exception this way.
window.alert = function (message) {
const keywordToIgnore = "resizeobserver";
const trimmedMessage = message.trim().toLowerCase();
if (trimmedMessage.includes(keywordToIgnore)) {
return;
}
swal({
html: message,
type: "info",
}).then(
function () {},
function () {}
);
};
I tried all solution , but these all are failed.
useEffect(() => {
const errorHandler = (e:any) => {
if (
e.message.includes(
"ResizeObserver loop completed with undelivered notifications" ||
"ResizeObserver loop limit exceeded"
)
) {
const resizeObserverErr = document.getElementById(
"webpack-dev-server-client-overlay"
);
if (resizeObserverErr) {
resizeObserverErr.style.display = "none";
}
}
};
window.addEventListener("error", errorHandler);
return () => {
window.removeEventListener("error", errorHandler);
};
}, [])
I am using DevExtreme (UI-Framework) for an Angular Application. I was able to fix the issue by using shorter labels and item names for my RadioGroups.
in component.html:
<dxi-item
[colSpan]="3"
dataField="dataField"
editorType="dxRadioGroup"
[editorOptions]="{ items: myItems, valueExpr: 'key', displayExpr: 'name', layout: 'horizontal' }"
>
<dxo-label text="ShortLabel needs to be short!"></dxo-label>
</dxi-item>
in component.ts:
myItems = [
{ key: false, name: "true" },
{ key: true, name: "false" },
];
This issues mostly raised with typography of multiline. if you have it on your screen with full width try removing multiline will fix your problem
I was having a similar issue in Antd Table
component while using scroll={{x:"max-content"}}
.
After removing this prop, it worked.
react-router-dom
hasn't much to do with any actual UI rendering (it matches a route to the URL path so your UI can render), so I suspect this issue with any resize observer is elsewhere. We can't help address issues in code we can't see though, so please do edit to include a minimal reproducible example of the relevant code you have issue working with and provide the error message and any code stacktrace as plain formatted test instead a picture of text. Images are less accessible, can be more difficult to read, and are not copy/pasteable. – Drew Reese Commented May 6, 2023 at 15:58react-router-dom
, that was just the only thing that had changed (the component itself had not). Anyway, I was able to isolate it to a single field in the form that the dialog was presenting. A field that Lastpass was trying to offer an autofill option for. Prevent LP from putting its icon in the text field solved the issue. – rjray Commented May 6, 2023 at 17:19<TextField multiline />
causing this issue. Don't know how to solve it. Help me ! – Prashant Commented Jan 13 at 15:27