react-data-grid icon indicating copy to clipboard operation
react-data-grid copied to clipboard

Issue when resizing page/grid

Open arbonaa opened this issue 2 years ago • 8 comments

Describe the bug

When the page is resized the following error is raised: ResizeObserver loop completed with undelivered notifications.

To Reproduce

  1. create react project or run create-react-app
  2. add react-data-grid
  3. add a basic datagrid
  4. run webpack dev server or npm start script
  5. resize the page

Link to code example:

const Grid = () => {
    const columns = [
        { key: 'id', name: 'ID' },
        { key: 'title', name: 'Title' }
      ];
      
      const rows = [
        { id: 0, title: 'Example' },
        { id: 1, title: 'Demo' }
      ];
    
    return (
        <>

            <DataGrid columns={columns} rows={rows} />
        </>
    )
}

Suspected code block causing the issue:

const resizeObserver = new ResizeObserver(entries => {
      const size = entries[0].contentBoxSize[0];
      flushSync(() => {
        setInlineSize(size.inlineSize);
        setBlockSize(size.blockSize);
      });
    });
    resizeObserver.observe(gridRef.current);
    return () => {
      resizeObserver.disconnect();
    };

I think the issue is with flushSync(), it can cause issues with the ResizeObserver loop if it triggers a re-render before the loop has finished running. Solution might be to wrap the setInlineSize and setBlockSize calls in a setTimeout with a delay of 0. This will allow the ResizeObserver loop to finish running before triggering a re-render.

const resizeObserver = new ResizeObserver(entries => {
      const size = entries[0].contentBoxSize[0];
      flushSync(() => {
        setTimeout(() => {
          setInlineSize(size.inlineSize);
          setBlockSize(size.blockSize);
        }, 0);
      });
    });
    resizeObserver.observe(gridRef.current);
    return () => {
      resizeObserver.disconnect();
    }

Expected behavior

No error raised when resizing window

Environment

  • react-data-grid version: 7.0.0-beta.36
  • react/react-dom version: 18.2.0
  • Web Browser version: Firefox Developer Edition 117.0b9

arbonaa avatar Aug 22 '23 14:08 arbonaa

Can see the same issue.

Appears when the rows do not fill the available height of the table.

In storybook this causes a constant reload of the story.

Temp fixed it by adding overflow-y: scroll to the grid wrapper.

react-data-grid version: "7.0.0-canary.49"

padamban-msci avatar Sep 06 '23 09:09 padamban-msci

I'm having the same issue in Microsoft Edge. Seems to be related to the grid when there are no rows as it happens consistently on load while getting the data to populate the grid.

+-- [email protected] +-- [email protected] +-- [email protected] +-- [email protected]

Microsoft Edge Version 119.0.2151.44 (Official build) (64-bit)

@padamban-msci, Not sure how you figured it out, but your temp fix works so thank you for sharing. :)

[UPDATE] I just noticed that even though the temp fix works on load, it does NOT fix if you then resize the browser. Seems to be more "sensitive" to sizing the browser smaller/narrower as it happens right away. Sizing larger/wider doesn't occur all the time and sometimes happens after a slight delay after the resizing.

AYColumbia avatar Nov 07 '23 14:11 AYColumbia

@AYColumbia

I had the similar issue, when I was shrinking the table.

It was commented in some stackoverflow question that is benign error. So, I disabled the react overlay for this kind of error.

Similar issue and recommendations:

  • https://github.com/adazzle/react-data-grid/pull/3261#issuecomment-1632389409
  • https://stackoverflow.com/questions/49384120/resizeobserver-loop-limit-exceeded

const WHITE_LIST = [
  'ResizeObserver loop completed with undelivered notifications.',
];

export const useDataGridErrorSuppressor = () => {
  useEffect(() => {
    window.addEventListener('error', (e) => {
      if (WHITE_LIST.includes(e.message)) {
        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');
        }
      }
    });
  }, []);
};
function DataGridWrapper() {
    useDataGridErrorSuppressor()
    ...
}

padamban-msci avatar Nov 09 '23 08:11 padamban-msci

@padamban-msci, Thank you for the detailed info. I'll take a look and give the recommendations a try.

AYColumbia avatar Nov 09 '23 12:11 AYColumbia

So I finally got around to adding this and it's not quite working as I had hoped. I do notice that we're really not fixing anything but just hiding the error. For some reason, the document.getElementById('webpack-dev-server-client-overlay-div') is returning null in my browser. When I query the overlay in dev tools, it does show the id as webpack-dev-server-client-overlay-div. So not sure why that particular element isn't being found.

I added some logging to log the message, error element and error div element, i.e.,

msg:  ResizeObserver loop completed with undelivered notifications.
err <iframe id=​"webpack-dev-server-client-overlay" src=​"about:​blank" style=​"display:​ none">​…​</iframe>​
errDiv null

This still happens AFTER applying the event handler. :( 2023-11-10 07_40_31-react data grid - ResizeObserver loop completed with undelivered notifications

AYColumbia avatar Nov 10 '23 13:11 AYColumbia

I wanted to add one more update to my post above. Since the one element is an iframe, I updated the code as such to get the document element from the iframe. The logging shows this now works, however, it's still NOT affecting the display of the overlay. BTW, I'm using Edge so have NOT tried this in Chrome since I don't use it.

	if (WHITE_LIST.includes(e.message))
	{
		const resizeObserverErr = document.getElementById('webpack-dev-server-client-overlay');
		if (resizeObserverErr)
		{
			const ifrmDoc = resizeObserverErr.contentDocument;
			resizeObserverErr.setAttribute('style', 'display: none');
			if (ifrmDoc)
			{
				const resizeObserverErrDiv = ifrmDoc.getElementById('webpack-dev-server-client-overlay-div');
				if (resizeObserverErrDiv)
				{
					resizeObserverErrDiv.setAttribute('style', 'display: none');
				}
			}
		}
	}

Log output shows elements found and style set.

err <iframe id="webpack-dev-server-client-overlay" src="about:blank" style="display: none">…</iframe>
errDiv <div id="webpack-dev-server-client-overlay-div" style="display: none">…</div>

AYColumbia avatar Nov 10 '23 14:11 AYColumbia

I'm also facing this issue, when data is first loading.

hitesh-pathak avatar Nov 30 '23 10:11 hitesh-pathak

encountered the same issue @padamban-msci temp solution works for me.

jmjuanico avatar Feb 03 '24 00:02 jmjuanico