timolins / react-hot-toast

Smoking Hot React Notifications 🔥
https://react-hot-toast.com
MIT License
9.66k stars 318 forks source link

Add `fetch()` error support in `toast.promise()` #190

Open madhurjain opened 2 years ago

madhurjain commented 2 years ago

Per MDN, the fetch() API only rejects a promise when a “network error is encountered, although this usually means permissions issues or similar.” Basically fetch() will only reject a promise if the user is offline, or some unlikely networking error occurs, such as DNS lookup failure.

fetch("http://httpstat.us/500")
  .then(function () {
    console.log("ok");
  })
  .catch(function () {
    console.log("error");
  });

The above code actually logs "ok" and not "error". Thus, the below code also shows a Data Saved! toast instead of expected Error saving changes due to a 500 status code.

const promise = fetch("http://httpstat.us/500");
toast.promise(promise, {
  loading: "Saving..",
  success: "Data Saved!",
  error: "Error saving changes",
});

The fix is to check for response.ok flag within the first .then() and throw an Error object to be caught so the toast correctly displays the error message.

References: https://www.tjvantoll.com/2015/09/13/fetch-and-errors/

timolins commented 2 years ago

Hi! Thanks for this issue. This is definitely a nice convenience feature when working with raw fetch(). I'll play with this when I get the next release rolling.

VieiraNT commented 1 year ago

Has this been fixed?

Tigerly1 commented 1 year ago

Fix it please!

mehdiBenzaghar commented 1 year ago

up 👀

shivpratik commented 1 year ago

Can we add functions on success in Toast Promise? For eg. when using with Nextjs 13 I want to refresh the server component after update in client component.

alexeigs commented 1 year ago

Fix?

pguardiario commented 1 year ago

bump

raburuz commented 11 months ago

Please fix :/

mimo-lbp commented 10 months ago

Please fix this, toast.promise() never trigger error even if i throw Error in my fetch call :/

Remrem08007 commented 10 months ago

@mimo-lbp Same here I throw the Error in my fetch call and it still doesn't display the error message.

saifulshihab commented 4 months ago

Per MDN, the fetch() API only rejects a promise when a “network error is encountered, although this usually means permissions issues or similar.” Basically fetch() will only reject a promise if the user is offline, or some unlikely networking error occurs, such as DNS lookup failure.

fetch("http://httpstat.us/500")
  .then(function () {
    console.log("ok");
  })
  .catch(function () {
    console.log("error");
  });

The above code actually logs "ok" and not "error". Thus, the below code also shows a Data Saved! toast instead of expected Error saving changes due to a 500 status code.

const promise = fetch("http://httpstat.us/500");
toast.promise(promise, {
  loading: "Saving..",
  success: "Data Saved!",
  error: "Error saving changes",
});

The fix is to check for response.ok flag within the first .then() and throw an Error object to be caught so the toast correctly displays the error message.

References: https://www.tjvantoll.com/2015/09/13/fetch-and-errors/

It would also be nice if the toast could catch the promise error & show the error message by default.

fzsf163 commented 1 month ago

I do not if this is gonna help. based on @saifulshihab 's answer I did following and it worked like charm. Thank you @saifulshihab

await toast.promise(
        fetch(API_CLOUDINARY, { method: "POST", body: formData })
          .then(async (res) => {
            if (res.ok === false) {
              let error = await res.json().then((e) => {
                return e.error.message;
              });
              throw new Error(error);
            } else {
              res.json();
            }
          })
          .then((data) => {
            console.log(data);
          }),
        {
          pending: "Uploading Image",
          success: "Upload Successful",
          error: {
            render({ data }) {
              return `${data}`;
            },
          },
        },
      );