react-hot-toast icon indicating copy to clipboard operation
react-hot-toast copied to clipboard

Redux - How to use react-hot-toast with async await Axios call

Open Jared-Dahlke opened this issue 4 years ago • 8 comments

hey guys, I saw the other question about this but it did not help me. I have tried multiple ways to get this to work but cannot seem to make it work.

I tried this:

export const postVersionBulkAction = (args) => {
	let url = `${apiBase}/smart-list/version/${args.versionId}/action`
	let promise = queue.wrap(async (dispatch) => {
		let params = { iabCategoriesActions: args.iabCategoriesActions }
		const result = await axios.patch(url, params)
		if (result.status === 200) {
		}
	})
	toast.promise(promise, {
		loading: 'Saving...',
		success: 'saved',
		error: 'error'
	})
}

but that gives me an error: 'TypeError: promise.then is not a function'

I've also tried this:

export const postVersionBulkAction = (args) => {
	let url = `${apiBase}/smart-list/version/${args.versionId}/action`
	return queue.wrap(async (dispatch) => {
		try {
			let params = { iabCategoriesActions: args.iabCategoriesActions }
			const result = await axios.patch(url, params)
			toast.promise(result, {
				loading: 'Saving...',
				success: 'saved',
				error: 'error'
			})
		} catch (error) {
			alert(error)
		}
	})
}

but i get 'promise.then is not a function' error on that one too.

I've also tried calling it like this:

	const promise = props.postVersionBulkAction(params)		
		toast.promise(promise, {
			loading: 'Saving...',
			success: <b>saved!</b>,
			error: <b>Could not apply.</b>
		})

but that way always fires the success toast even if it fails.

Any idea how i could make this work?

PS. thanks for the awesome product! Other than this problem it has helped me so much, and I have succesfully removed thousands of lines of redux boilerplate because of this library. thanks again

Jared-Dahlke avatar Feb 09 '21 15:02 Jared-Dahlke

Hey! I'm not entirely sure what is going on but I think it should work like this:

const promise = axios.patch(url, params)

toast.promise(promise, {
  loading: 'Saving...',
  success: <b>saved!</b>,
  error: <b>Could not apply.</b>
})

const result = await promise

timolins avatar Feb 09 '21 15:02 timolins

Hey! I'm not entirely sure what is going on but I think it should work like this:

const promise = axios.patch(url, params)

toast.promise(promise, {
  loading: 'Saving...',
  success: <b>saved!</b>,
  error: <b>Could not apply.</b>
})

const result = await promise

It is still popping up as a success when I try your way even when the network call is failing with a 404:

export const postVersionBulkAction = (args) => {	
	return async (dispatch) => {		
		const promise = axios.patch(badUrl,  params )
		toast.promise(promise, {
			loading: 'Saving...',
			success: 'saved',
			error: 'error'
		})

		const result = await promise
	}
}

it pops up a success immediately

Edited: removed some of the extraneous stuff from the function to make it easier for someone to diagnose

Jared-Dahlke avatar Feb 09 '21 16:02 Jared-Dahlke

@JaredDahlke did you ever resolve this? I am also seeing this error when trying to write a unit test for a component using toast.promise

lsbyerley avatar Jun 04 '21 14:06 lsbyerley

Have you tried ensuring your .catch was first and .then following it? Weirdly enough, that fixed this same issue for me.

 const callMyFunction = callFunction({ username: this.state.username })
      .catch((error) => {
        // Getting the Error details.
        console.error(error.message);
        return error.message;
      })
      .then((res) => {
        console.log(res);
        refreshData();
      });

    toast.promise(callMyFunction, {
      loading: "Loading...",
      success: "Everything went smoothly.",
      error: "Uh oh, there was an error!",
    });

(I know this isn't an Axios example, but the promise structure is relatively the same)

ingusjan avatar Jul 30 '21 11:07 ingusjan

The toast.promise function returns the promise, so you could use something like this:

const callMyFunction = toast.promise(callFunction({ username: this.state.username }), {
      loading: "Loading...",
      success: "Everything went smoothly.",
      error: "Uh oh, there was an error!",
    });
callMyFunction.then((res) => {
    console.log(res);
    refreshData();
})
 .catch((error) => {
        // Getting the Error details.
        console.error(error.message);
        return error.message;
      });
      

    

gamino97 avatar Sep 03 '21 00:09 gamino97

This worked for me

const res = fetch(apiUrl);

    toast.promise(res, {
      loading: 'Loading ...',
      success: (data) => {
        console.log(data);
        if (data.status === 500) throw new Error('server error');
        return 'Everything went smoothly.';
      },
      error: 'Uh oh, there was an error!',
    });

gugocharade avatar Mar 08 '22 13:03 gugocharade

Here is what works for

const promise = axios.patch(url, params)

toast.promise(promise, {
  loading: 'Saving...',
  success: <b>saved!</b>,
  error: <b>Could not apply.</b>
},
, {
   style: {
    minWidth: '250px',
   }
 }
)
.then((r) => r)
.catch((error) => error);

tlhabane avatar Mar 10 '22 18:03 tlhabane

In case anyone using firebase:

 toast.promise(
      createUserWithEmailAndPassword(authInstance, email, password),
      {
        loading: "loading...",
        success: (result) => `success, ${result.user}`,
        error: (e) => `error ${e.message}`,
      }
    );

amanzrx4 avatar Sep 05 '22 10:09 amanzrx4

In my case, make sure you throw an error after doing a catch

This Work for me

 const callMyFunction = callFunction({ username: this.state.username })
      .catch((error) => {
        // Getting the Error details.
        console.error(error.message);
        throw error; // throw again after you catch
      })
      .then((res) => {
        console.log(res);
        refreshData();
      });

    toast.promise(callMyFunction, {
      loading: "Loading...",
      success: "Everything went smoothly.",
      error: "Uh oh, there was an error!",
    });

axquired24 avatar Oct 05 '22 07:10 axquired24

In case anyone using firebase:

 toast.promise(
      createUserWithEmailAndPassword(authInstance, email, password),
      {
        loading: "loading...",
        success: (result) => `success, ${result.user}`,
        error: (e) => `error ${e.message}`,
      }
    );

Thanks a lot, this work for me...

TheJazzDev avatar Jan 09 '23 01:01 TheJazzDev

This is a bit tricky due to the next:

  • The server errors are not handled as an error within javascript
  • We expect errors from the server as normal error

I solved this by doing the next: throwing an error from the my toast code if the server was not sending the expected/ok statues.

toast.promise(fetch(someURL), {
      loading: "Loading ...",
      success: data => {
        if (!data.ok) { //here you can that this will throw the error from the returned data. Usually it's treated as normal thing.
          throw new Error(`Statues code ${data.status}`);
        }
        return "Everything went good";
      },
      error: e => {
        return `Uh oh, there was an error! ${e.message}`;
      },
    })

a0m0rajab avatar May 25 '23 18:05 a0m0rajab