adazzle / react-data-grid

Feature-rich and customizable data grid React component
https://adazzle.github.io/react-data-grid/
Other
6.93k stars 2.18k forks source link

Issue when resizing page/grid #3314

Open arbonaa opened 1 year ago

arbonaa commented 1 year ago

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

padamban-msci commented 1 year ago

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"

AYColumbia commented 11 months ago

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.

+-- react-data-grid-addons@7.0.0-alpha.24 +-- react-data-grid@7.0.0-beta.40 +-- react-dom@18.2.0 +-- react-hooks@1.0.1

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.

padamban-msci commented 11 months ago

@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:


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()
    ...
}
AYColumbia commented 11 months ago

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

AYColumbia commented 11 months ago

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 commented 11 months ago

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>
hitesh-pathak commented 10 months ago

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

jmjuanico commented 8 months ago

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