petyosi / react-virtuoso

The most powerful virtual list component for React
https://virtuoso.dev
MIT License
5.13k stars 299 forks source link

[BUG] Uncaught Error: ResizeObserver loop completed with undelivered notifications. #1049

Closed Alic-Chen closed 5 months ago

Alic-Chen commented 5 months ago

react-virtuoso-issue

NiestrojMateusz commented 5 months ago

We faced the same issue after upgrade to 4.7.x with react@18.2.0

petyosi commented 5 months ago

Can you try adding (and calling) the following hook to your application? You need to add it only once. Please let me know if this works for you @NiestrojMateusz @Alic-Chen

function useSuppressResizeObserverError() {
  React.useEffect(() => {
    const cb = (e: ErrorEvent) => {
      if (
        e.message ===
        "ResizeObserver loop completed with undelivered notifications."
      ) {
        e.stopImmediatePropagation();
        e.preventDefault();
      }
    };
    window.addEventListener("error", cb);
    return () => {
      window.removeEventListener("error", cb);
    };
  }, []);
}

To clarify, the error is harmless, in fact there was a working draft for the browsers to implement means of avoiding it.

petyosi commented 5 months ago

Another way to silence this error if you're using webpack dev server is to set your dev server config like so:

        devServer: {
          client: {
            overlay: {
              errors: true,
              warnings: false,
              runtimeErrors: false, // this eliminates the error. 
            },
          },
        },
Alic-Chen commented 5 months ago

Can you try adding (and calling) the following hook to your application? You need to add it only once. Please let me know if this works for you @NiestrojMateusz @Alic-Chen

function useSuppressResizeObserverError() {
  React.useEffect(() => {
    const cb = (e: ErrorEvent) => {
      if (
        e.message ===
        "ResizeObserver loop completed with undelivered notifications."
      ) {
        e.stopImmediatePropagation();
        e.preventDefault();
      }
    };
    window.addEventListener("error", cb);
    return () => {
      window.removeEventListener("error", cb);
    };
  }, []);
}

To clarify, the error is harmless, in fact there was a working draft for the browsers to implement means of avoiding it.

I'm sorry! That doesn't solve my problem

petyosi commented 5 months ago

@Alic-Chen can you reproduce your problem - either in a sandbox or in a repository, so that I can examine it? As far as I can tell, this eliminates the error in a sandbox environment.

Alic-Chen commented 5 months ago

image

I have a requirement, the image is obtained from the database, the image height is adaptive according to the width, and do lazy loading processing, when I scroll the page, the console will keep printing "Uncaught Error: ResizeObserver loop completed with undelivered notifications. ", the page will continue to blink until the console stops printing errors. So I'm guessing it's a mistake. Excuse me next useSuppressResizeObserverError invoke this method should be in what place? Can you provide me with a demo? Thank you!

petyosi commented 5 months ago

@Alic-Chen I believe you're facing a different problem than the one I had in mind. Most likely, you're trying to do something that the virtuoso grid does not support. It needs static-sized, same-size items to work correctly.

I believe that my instructions for the hook above are clear enough, However, they will not help you.

markwoon commented 5 months ago

@petyosi Is the expectation that we need to use one of the workarounds above, or is there something react-virtuoso can do to avoid this warning?

petyosi commented 5 months ago

@markwoon I'm trying to gather enough details from the users to understand if the hook is a viable solution. Once I know enough, I will most likely include it in the component initialization. Does it work for you?

The webpack dev server problem is not solvable from the component, I'm afraid. They bind to it unconditionally, as far as I can tell.

To clarify, the reason why this error occurs is that the component reacts to item resizing and re-fills with new items. This is a legit approach. if I delay the action with something like requestAnimationFrame, the component would be much more sluggish when scrolling.

Methuselah96 commented 5 months ago

I am experiencing this error in Cypress, and unfortunately Cypress also listens to error events and fails the test if an error is encountered. I tried the above solution, but the Cypress error event handler is getting called before useSuppressResizeObserverError's error callback.

petyosi commented 5 months ago

@Methuselah96 - I'm not a cypress user, but it looks like this issue is very relevant? https://github.com/cypress-io/cypress/issues/8418. Can't deduct a definitive answer on how to do it, though. Please let me know if you figure something out.

paulincai commented 5 months ago

@petyosi as I understand you are looking for some user feedback, I implemented the hook. It blocks most of the errors now however there are still some which are not blocked. I noticed that those which are not blocked are mostly occurring when a new react route loads (e.g. I am moving from a user profile to another user profile and then to the main wall of feeds). I use the "simple" Virtuoso (no grid/table etc) When I scroll in a Virtuoso list is where you can see all those blocked errors.

Screenshot 2024-03-28 at 11 29 25 PM

Methuselah96 commented 5 months ago

I wonder if using useLayoutEffect instead of useEffect would help with the errors that show up when a new route loads?

petyosi commented 5 months ago

@paulincai - my guess is that you're using the hook somewhere in a specific route. I think it's better to put it on an app level so that it's executed once, no point in doing re-subscriptions. Let me know if my guess is correct.

paulincai commented 5 months ago

@petyosi unfortunately I was at the top of React - top most component that is mounted on the generic id='app' in the initial HTML. Meanwhile, I moved it into my startup which runs before React even renders and I still get those. I know most of them are being blocked. In the image there is a url field. All those 57 message have been generated scrolling the list at that url, with no routing changes

Screenshot 2024-03-29 at 5 51 15 PM

petyosi commented 5 months ago

I guess moving it there should have worked, not sure from your post. Hard to say what goes on in this case, a reproduction would help.

I am not sure where this screenshot is from, looks like an error reporting tool (Centry?). If so, check this thread.

paulincai commented 5 months ago

I added a bit to my comment above. All those errors occur at the same url with no routing. The reporting tool is specific to MeteorJS. It just sends whatever the browser says (or the server)

paulincai commented 5 months ago

I personally don't have a problem with them. I have options in the reporting tool to just ignore them and don't get notified for them. I just wanted to let you know that probably the frequency at which they are generated is high and the listener disregards some.

petyosi commented 5 months ago

@paulincai (and everyone else in this thread) can you please test v4.7.7? Thank you!

Methuselah96 commented 5 months ago

v4.7.7 fixes the errors I was getting in Cypress, thanks!

petyosi commented 5 months ago

This problem should be solved in v4.7.7.

paulincai commented 5 months ago

I can also confirm these messages are gone away 100%. Thank you very much @petyosi for your effort.

carlcodes commented 5 months ago

thank you for fixing this!!