Create beautiful loading notification in React in 20 lines of code!

ashish - May 17 '22 - - Dev Community

The Idea

I'll be honest here, JavaScript alerts on browsers suck! I've been trying to find the perfect library to create notification and toasts easily in react and here's what I found out 😀

The Library

I was able to find some react component library for creating toasts but the easiest to implement and cleanest library that I found was react-hot-toast, Warning: It's too hot!

Creating the toast

Using the library is pretty easy, and there are a a number of different toasts available which you can check out in their docs page, but for this blog, we will focus on the promise toast to create a loading notification when we fetch data from an API.

Let's start by creating a react project.

Dependencies I installed in the example app:

  • tailwind
  • react-hot-toast

Let's quickly get to the part where we fetch data from an API. I have an API to get my Spotify data and I'll be using that here.

My app.jsx file:

import { useState } from 'react'
import toast, { Toaster } from 'react-hot-toast';

function App() {
  const [data, setData] = useState(null)
  function fetchData() {
    return fetch('https://spotify-np-api.vercel.app/api').then(
      (response) => {
        return response.json();
      }
    ).then(
      (data) => {
        return data;
      }
    ).catch(
      (error) => {
        console.error(error);
      }
    )
  }
  const getToast = () => {
    toast.promise(fetchData(), {
      loading: 'getting song data...',
      success: (data) => {
        setData(data)
        return 'fetched top song data'
      },
      error: "couldn't fetch data!",
    })
  }

  return (
    <div className="relative App flex justify-center items-center bg-red-200 w-screen h-screen flex-col gap-3 p-3">
      <button onClick={getToast} className='hover:rotate-3 duration-300 bg-red-400 -rotate-3 shadow-xl rounded-md px-6 py-2 text-rose-100 font-bolder' >🎵ㅤGet Song Data</button>
      {data && 
        <div className='hover:-rotate-1 duration-300 cursor-pointer bg-red-400 flex flex-col rotate-1 justify-center items-center h-1/4 w-full lg:w-1/3 md:w-1/2 shadow-2xl rounded-md p-4'>
          <h1 className='text-center text-2xl mb-3 text-red-100 font-bold'>ashish's top song for this week 🎵</h1>
          <h1 className='text-center text-xl font-bolder text-rose-100'>{data.top.song.toLowerCase()}</h1>
          <h1 className='text-center text-md font-bolder text-rose-200'>~ {data.top.artist}</h1>
        </div>
      }
      <h2 className='text-red-600 text-sm absolute bottom-0 text-center p-4'>made by ashish using react-hot-toast</h2>
      <Toaster
        toastOptions={{
          className: '',
          style: {
            background: '#f87171',
            color: '#ffe4e6',
          }
        }}
      />
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Let's break it down now.

Function for fetching and returning the promise, It returns the promise to be used by our toast method:

...
function fetchData() {
  return fetch('https://spotify-np-api.vercel.app/api').then(
    (response) => {
      return response.json();
    }
  ).then(
    (data) => {
      return data;
    }
  ).catch(
    (error) => {
      console.error(error);
    }
  )
}
...
Enter fullscreen mode Exit fullscreen mode

Now let's implement our react-hot-toast! First of all we will need to import it in our file.

import toast, { Toaster } from 'react-hot-toast';
...
Enter fullscreen mode Exit fullscreen mode

OnClick function using toast.promise(), we need to pass our promise in the toast.promise() method and the second argument is an object msgs where we define the messages that the toast needs to show based on promise state. Note that you can use a function to set states and change data in here too. I have used setData() to update the data to be displayed on app if the promise is fetched successfully.

...
const getToast = () => {
  toast.promise(fetchData(), {
    loading: 'getting song data...',
    success: (data) => {
      setData(data)
      return 'fetched top song data'
    },
    error: "couldn't fetch data!",
  })
}
...
Enter fullscreen mode Exit fullscreen mode

We need to add the <Toaster /> component at the end of our app to render the toast, You can style the toast here using ToastOptions object passed to it.

...
<Toaster
  toastOptions={{
    className: '',
      style: {
      background: '#f87171',
      color: '#ffe4e6',
    }
  }}
/>
...
Enter fullscreen mode Exit fullscreen mode

Now let's create a div component to show the fetched data.

...
{data && 
        <div className='hover:-rotate-1 duration-300 cursor-pointer bg-red-400 flex flex-col rotate-1 justify-center items-center h-1/4 w-full lg:w-1/3 md:w-1/2 shadow-2xl rounded-md p-4'>
          <h1 className='text-center text-2xl mb-3 text-red-100 font-bold'>ashish's top song for this week 🎵</h1>
          <h1 className='text-center text-xl font-bolder text-rose-100'>{data.top.song.toLowerCase()}</h1>
          <h1 className='text-center text-md font-bolder text-rose-200'>~ {data.top.artist}</h1>
        </div>
      }
...
Enter fullscreen mode Exit fullscreen mode

And with this, we have successfully made a simple app to fetch data from API and show it with a beautiful toast. Here's what the final app looks like:
gif

Thanks for reading if you made it till here, Hit me up with questions or anything you want to ask in comments, I will reply asap :)

Source Code

. . . . . . . . . . . . . . . . . . . . . . . . . .