Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS: Warning: Cannot update a component (`x`) while rendering a different component (`y`) with global popup notifier

i've portal which basically notifies a user with a popup if there are some new data.

Now my problem is that on first render (when i reload the page or first render of UseToastComponent with toasts.length>0) i get

Warning: Cannot update a component (`UseToastComponent`) while rendering a different component (`Layout`). To locate the bad setState() call inside `Layout`...

Now i've tried diffrent tecniques but couldn't solve it.

I've UseToastComponent

imported in _app.js like this :

   <QueryClientProvider client={queryClient}>
        <UseToastComponent settings={{ autoClose: false }} />
        {getLayout(<Component {...pageProps} />)}
      </QueryClientProvider>

Let's look at my UseToastComponent

    return (
        <>
          {loaded &&
            ReactDOM.createPortal(
              <div className="mb-6 mr-6">
                {toasts.map((toast) => (
                  <PopupNotification
                    key={toast.id}
                    ...
                    ...
                  />
                ))}
              </div>,
              document.getElementById(portalId)
            )}
        </>
      );

Now toasts is global state that is beign updated every x sec in Layout component as it's global

How i update toast (global state) in layout comp

data.data.documents.forEach((doc) => {
  addToast({
   ...
   ...
  });
});

For any more information ask me, thanks

EDIT:

can it be because i update a state in layout?

if (dayjs(data.data.documents[0].createdAt).isAfter(firstTimeCreated)) {
      setFirstTimeCreated(data.data.documents[0].createdAt);
    }
    data.data.documents.forEach((doc) => {
  addToast({
   ...
   ...
  });
});

EDIT 1 : working example https://codesandbox.io/p/sandbox/reverent-monad-76jwg5

like image 265
Singh Avatar asked Feb 07 '26 06:02

Singh


1 Answers

In the layout, add the if inside an useEffect:

  useEffect(() => {
    if (data && data.status === 200 && !isLoading) {
      if (data.data.results.length > 0) {
        data.data.results.forEach((v) => {
          addToast({ circle: v.gender, text: v.name.title });
        });
      }
    }
  })

Don't know the exact reason, but with the useEffect, next will wait for the Layout to render, to add a toast, becausing adding a toast makes the useToastComponent rerender, and they cannot rerender at the same time, or you will that error

like image 148
Paulo Fernando Avatar answered Feb 09 '26 09:02

Paulo Fernando