Design Converter
Education
Last updated on Mar 6, 2025
•6 mins read
Last updated on Mar 6, 2025
•6 mins read
Software Development Executive - II
I know who I am.
Building a responsive React app?
Keeping track of element size changes is a big part of it. The ResizeObserver API helps by watching individual elements instead of relying on global window resize events.
But sometimes, React developers run into a common warning:
"ResizeObserver loop completed with undelivered notifications."
This happens when the observer detects size changes but can’t process all updates in a single cycle. While it’s usually harmless, frequent warnings might signal performance issues or endless resize loops. If a component keeps changing sizes without settling, the callback might be firing too often—leading to unnecessary re-renders.
Let's break down what causes this and how to fix it.
The ResizeObserver API allows React components to respond to changes in the size of an element. Unlike the traditional window.onresize event, ResizeObserver lets you monitor a specific component or DOM element. This is particularly useful in React for managing dynamic layouts, scaling media (such as video players), or adapting complex UIs.
A typical implementation in a React component involves:
• Creating a reference using useRef
• Observing the element inside a useEffect hook
• Cleaning up the observer on unmount
Here’s a simple example:
1import React, { useEffect, useRef, useState, useMemo } from 'react'; 2 3const ExampleComponent = () => { 4 const elementRef = useRef(null); 5 const [size, setSize] = useState({ width: undefined, height: undefined }); 6 7 useEffect(() => { 8 if (!elementRef.current) return; 9 10 const observer = new ResizeObserver((entries) => { 11 if (!entries.length) return; 12 const entry = entries[0]; 13 const newWidth = Math.round(entry.contentRect.width); 14 const newHeight = Math.round(entry.contentRect.height); 15 setSize({ width: newWidth, height: newHeight }); 16 }); 17 18 observer.observe(elementRef.current); 19 20 return () => { 21 observer.unobserve(elementRef.current); 22 observer.disconnect(); 23 }; 24 }, []); 25 26 return ( 27 <div ref={elementRef}> 28 <p>The element size is {size.width}px x {size.height}px.</p> 29 </div> 30 ); 31}; 32 33export default ExampleComponent;
When you see this warning in your browser console, it indicates that while the ResizeObserver has registered size changes, some notifications have not been delivered in the current cycle. In a React context, this may happen if:
• Excessive Resize Events: Rapid updates (e.g., during animations or transitions) can overwhelm the observer.
• Third-Party Extensions: Extensions like LastPass might inject elements or modify inputs, causing unexpected resize events. Third-party browser extensions like LastPass can trigger the ResizeObserver error by modifying layout elements.
• Application Bugs: A state update or layout adjustment in a component might inadvertently trigger a new resize event, causing a loop.
• Framework-Generated Re-renders: React’s re-rendering, especially when coupled with dynamic layout calculations, can result in repetitive resize notifications.
To diagnose the root cause of the warning in a React app:
Test your application in an incognito window (with extensions disabled) to determine if a third-party extension is triggering extra notifications. Using incognito mode can help determine if a browser extension is causing the ResizeObserver error.
Review your component’s resize handlers. Verify that your updates are not causing recursive changes. For example, if you update an element’s size in response to a resize event, ensure that the update isn’t immediately causing another resize.
Monitor component re-renders and inspect the DOM element to check for unintended size modifications.
If you’re using UI libraries or custom hooks that incorporate ResizeObserver, check for open issues or recommended configurations specific to React.
If you encounter this warning during end-to-end testing with Cypress, you can instruct Cypress to ignore it:
1const resizeObserverLoopErrRe = /^ResizeObserver loop limit exceeded/; 2Cypress.on('uncaught:exception', (err) => { 3 if (resizeObserverLoopErrRe.test(err.message)) { 4 return false; 5 } 6});
This snippet prevents the test runner from failing due to this warning.
To avoid cluttering your error reports in Sentry, add the warning to your ignore list:
1import * as Sentry from '@sentry/react'; 2 3Sentry.init({ 4 dsn: 'your_dsn_here', 5 ignoreErrors: ['ResizeObserver loop limit exceeded'], 6});
This configuration prevents unnecessary noise in your production error monitoring while you focus on actual issues.
To effectively address the warning in a React application, consider the following strategies:
Always clean up your ResizeObserver in the useEffect cleanup function. This prevents memory leaks and redundant observations:
1useEffect(() => { 2 if (!elementRef.current) return; 3 4 const observer = new ResizeObserver((entries) => { 5 // Handle resize logic here 6 }); 7 8 observer.observe(elementRef.current); 9 10 return () => { 11 observer.unobserve(elementRef.current); 12 observer.disconnect(); 13 }; 14}, []);
Rapid size changes can trigger too many notifications. Use a debouncing strategy to limit how frequently your callback executes. Debouncing events can help avoid the ResizeObserver loop completed with undelivered notifications error.
1import { debounce } from 'lodash'; 2 3useEffect(() => { 4 if (!elementRef.current) return; 5 6 const handleResize = debounce((entries) => { 7 if (!entries.length) return; 8 const entry = entries[0]; 9 setSize({ 10 width: Math.round(entry.contentRect.width), 11 height: Math.round(entry.contentRect.height), 12 }); 13 }, 100); 14 15 const observer = new ResizeObserver(handleResize); 16 observer.observe(elementRef.current); 17 18 return () => { 19 observer.unobserve(elementRef.current); 20 observer.disconnect(); 21 handleResize.cancel(); // Cancel any pending debounced calls 22 }; 23}, []);
When processing resize events, be cautious not to trigger additional DOM updates that cause another resize. Instead, make minimal and idempotent updates. For instance, if you need to adjust component layout, consider using window.requestAnimationFrame to defer changes until after the observer’s loop completes:
1useEffect(() => { 2 if (!elementRef.current) return; 3 4 const observer = new ResizeObserver((entries) => { 5 entries.forEach((entry) => { 6 window.requestAnimationFrame(() => { 7 // Apply size updates in a controlled manner 8 setSize({ 9 width: Math.round(entry.contentRect.width), 10 height: Math.round(entry.contentRect.height), 11 }); 12 }); 13 }); 14 }); 15 16 observer.observe(elementRef.current); 17 18 return () => { 19 observer.unobserve(elementRef.current); 20 observer.disconnect(); 21 }; 22}, []);
Avoid attaching ResizeObserver to a large number of elements. In React, it’s best to observe only the elements that require dynamic adjustment. This reduces the load and potential for recursive notifications.
To harness the full potential of ResizeObserver while avoiding performance pitfalls, keep these best practices in mind:
• Use ResizeObserver Sparingly: Only observe elements where size changes directly affect your component’s rendering.
• Optimize Callback Functions: Write efficient resize callbacks that avoid triggering additional layout recalculations.
• Implement Debouncing or Throttling: This minimizes the frequency of updates and prevents the observer from being overwhelmed.
• Ensure Proper Cleanup: Use React’s useEffect hook to connect and disconnect the observer to avoid lingering observers and memory leaks.
• Test Thoroughly: Regularly check your application’s behavior across various screen sizes and devices using React DevTools and browser debugging tools.
The "ResizeObserver loop completed with undelivered notifications" warning is a sign that layout adjustments might be causing performance issues. In React, small changes like debouncing resize callbacks, cleaning up effects properly, and avoiding unnecessary updates can help keep things smooth.
By applying these fixes, React components stay responsive without unnecessary re-renders or infinite loops. Keeping up with best practices and learning from the developer community will help maintain a well-performing app.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.