fkhadra / react-toastify

React notification made easy 🚀 !
https://fkhadra.github.io/react-toastify/introduction
MIT License
12.34k stars 676 forks source link

toast.update fail sometimes #928

Open lokomass opened 1 year ago

lokomass commented 1 year ago

Hi.

Before sending a request to my back, I create a toast with a loading gif inside, and a blue background like this :

image

When, I receive a response from my back, I update my toast : set it to success or error, and change text/background. It's work 9 times out of 10...

Sometimes, toast.update update only text inside but not className and type.

Here is an example call to back :

export const myTest = () => {
  const toast = get_id(6) //random id generated
  print_loading(toast)
  return (dispatch) => {
    const data = JSON.stringify({
      //...
    })
    api(data)
      .then(data => {
        if (data.status === 'OK') {
          update_toast(toast, data.response, 'success')
        } else {
          update_toast(toast, data.response, 'error')
        }
      })
      .catch(() => {
        update_toast(toast, undefined, 'error')
      })
  }
}

This in my toast functions :

// print loading toast
export function print_loading(id, texte = () => <CircularProgress style={white}/>, delay = 5000) {
  toast.info(texte, {
    toastId: id,
    icon: false,
    draggable: true,
    autoClose: delay,
    theme: 'colored',
    closeButton: false,
    pauseOnHover: true,
    closeOnClick: true,
    progress: undefined,
    hideProgressBar: true,
    position: 'bottom-right',
    bodyClassName: 'circular-toast',
    className: (typeof texte !== 'string')
      ? 'loading-toast'
      : undefined
  })
}
//update the toast
export function update_toast(id, texte = 'Une erreur est survenue', type = 'success') {
  toast.update(id, {
    type: type,
    delay: 500,
    icon: false,
    render: texte,
    draggable: true,
    theme: 'colored',
    closeButton: false,
    pauseOnHover: true,
    closeOnClick: true,
    progress: undefined,
    className: undefined,
    hideProgressBar: true,
    position: 'bottom-right',
    autoClose: 5000
  })
}

And the result of 10 test :

image

On of them is text updating but not parent class and type.

Here is my css :

.loading-toast .circular-toast {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0!important;
  margin: 0!important;
}
.loading-toast .circular-toast > div {
  display: flex;
  flex: 0 0!important;
}
.loading-toast {
  width: 64px;
  height: 64px;
}

Thansk for helping

lokomass commented 1 year ago

Here is a sandbox, but this doesn't reproduce my problem, it's inexplicable : https://codesandbox.io/s/magical-water-t3o9nr?file=/src/App.js

lokomass commented 1 year ago

I'm using 9.0.1 version, and same issue with last version

fkhadra commented 1 year ago

@lokomass if you are not able to reproduce the issue but still have it in your project, I suspect that something is happening on your side. Really hard to tell what is going on this way.

Have you thought about using the toast.promise API?

https://fkhadra.github.io/react-toastify/promise/

jkoufalas commented 8 months ago

ive been getting this issue too.

i have been using this with tanstack react-query to notify users of theire actions i use an toast.info on the API initial request to tell the user that they have sent the request and once the API sends back a success or error it will update the same toast with the results and appropriate type.

i use this for long requests so the user knows that the site is processing their request.

but it is only happening sometimes, almost all the time it will work and update the toast with the success and all is good, but every now and then the update wont work and from that point on all updates dont work until i refresh the page.

const mutation = useMutation(update, {
    onMutate: (data: TUpdate<any>) => {
      const message = data.message ? data.message : "Updating Record";
      setOriginalMessage(message);

      const id = toast.info(createMessage(message), { autoClose: false });
      setToastId(id);

      if (onMutate) {
        onMutate(data);
      }
    },
    onError: (data: any) => {
      if (data.errors) {
        const entries: [string, string[]][] = Object.entries(data.errors);
        entries.forEach(([key, errors]) => {
          handleErrors(errors, key);
        });
      } else if (data.error) {
        handleError(data.error);
      } else if (data.result) {
        queryClient.invalidateQueries(refetchKeys);
        ensureToastIsActive("warning", "Submission Halted - Validation Issues");
      }
      if (onError) {
        onError(data);
      }
    },
    onSuccess: (data: any) => {
      if (data.errors) {
        const entries: [string, string[]][] = Object.entries(data.errors);
        entries.forEach(([key, errors]) => {
          handleErrors(errors, key);
        });
      } else if (data.error) {
        console.log("data -------------- error ", data);

        handleError(data.error);
      } else if (data.result) {
        console.log("data -------------- success ", data);

        queryClient.invalidateQueries(refetchKeys);
        ensureToastIsActive("success", `${originalMessage} - Succeeded` ?? "");
      } else {
        console.log("data -------------- ", data);
      }
      if (onSuccess) {
        onSuccess(data);
      }
    },
  });

  const ensureToastIsActive = (type: "error" | "success" | "warning", render: string) => {
    console.log("toastId -- ", toastId);
    if (toastId !== null) {
      console.log("toast.isActive(toastId) -- ", toast.isActive(toastId));
    }
    if (toastId !== null && !toast.isActive(toastId)) {
      setToastId(toast[type](render));
    } else if (toastId !== null) {
      console.log(`got here --- type: ${type} - render: ${render}`);

      toast.update(toastId, {
        type: type,
        render: render,
        autoClose: 5000,
      });
    }
  };

when it wasn't working i used those traces to see if there was anything entering the toast to cause it an issue, but it all looks good.