DEV Community

Cover image for React-toastify v8 is live
Fadi Khadra
Fadi Khadra

Posted on

React-toastify v8 is live

Never heard of react-toastify before? Go check the demo

React-toastify has been around for 5 years(will turn five the 8 November πŸŽ‚). Since the beginning, one of the goals was to provide a library that is highly customizable and also able to work out of the box. Every major release introduces breaking changes but this is for the best πŸ‘Œ.

What is new in v8

Who doesn't like icons

Let's break down what is happening in the gif above. Notifications of different types (toast.info, toast.error, toast.success, toast.warning) display an icon associated with the selected type. You can also notice that the progress bar color matches the type color.

Don't be afraid 😱, if you don't like those icons you can use your own or remove them. This is what it looks like in practice.

toast("Default toast behavior is untouched, no icon to display");
toast.info("Lorem ipsum dolor"); // same as toast(message, {type: "info"});
toast.error("Lorem ipsum dolor")
toast.success("Lorem ipsum dolor")
toast.warn("Lorem ipsum dolor")
toast.error("Without icon", {
  icon: false
});
toast.success("You can provide any string", {
  icon: "πŸš€"
});
// custom icons have access to the theme and the toast type
toast.success("And of course a component of your choice", {
  icon: MyIcon
});
toast.success("Even a function, given you return something that can be rendered", {
  icon: ({theme, type}) =>  <img src="url"/>
});
//Disable icons
<ToastContainer icon={false} />
Enter fullscreen mode Exit fullscreen mode

Clear separation between type and theme

Prior to v8, toast.info, toast.error, etc... Would display respectively a blue notification, a red notification, etc... This is not the case anymore. There are 3 distinct themes: light, dark, colored. The theme can be applied globally or per notification.

//Set the theme globally 
<ToastContainer theme="dark" />

// define per toast
toast.info("Display a dark notification of type info");
toast.info("Display a light notification of type info", { theme: "light" });
toast.info("Display a blue notification of type info", { theme: "colored" });
Enter fullscreen mode Exit fullscreen mode

This separation will benefit theming in the future.

I promise this is new, I'll tell you if you await

v8-promise
v8-promise-resolved

The library exposes a toast.promise function. Supply a promise and the notification will be updated if it resolves or fails. When the promise is pending a spinner is displayed. Again you hide it, I bet you already know how toπŸ˜†.

Let's start with a simple example

const resolveAfter3Sec = new Promise(resolve => setTimeout(resolve, 3000));
toast.promise(
    resolveAfter3Sec,
    {
      pending: 'Promise is pending',
      success: 'Promise resolved πŸ‘Œ',
      error: 'Promise rejected 🀯'
    }
)
Enter fullscreen mode Exit fullscreen mode

Displaying a simple message is what you would want to do in 90% of cases. But what if the message you want to display depends on the promise response, what if you want to change some options for the error notification? Rest assured, under the hood, the library uses toast.update. Thanks to this, you have full control over each notification.

const resolveWithSomeData = new Promise(resolve => setTimeout(() => resolve("world"), 3000));
toast.promise(
    resolveAfter3Sec,
    {
      pending: 'Promise is pending',
      success: {
        render({data}){
          return `Hello ${data}`
        },
        // other options
        icon: "🟒",
      },
      error: {
        render({data}){
          // When the promise reject, data will contains the error
          return <MyErrorComponent message={data.message} />
        }
      }
    }
)
Enter fullscreen mode Exit fullscreen mode

Because you have the full power of toast.update, you can even supply a custom transition if you want 🀯
v8-promise-resolved

If you want to take care of each step yourself you can use toast.loading and update the notification yourself.

const id = toast.loading("Please wait...")
//do something else
toast.update(id, { render: "All is good", type: "success" });
Enter fullscreen mode Exit fullscreen mode

Pass data even when you are not rendering a react component

One way to pass data to the notification was to use the context api or provide your own component. Starting v8 a data option is now available to make it easier.

toast(({data}) => `Hello ${data}`, {
  data: "world"
})
Enter fullscreen mode Exit fullscreen mode

I just want to change few colors

Most of the time, users are ok with the default style, they just want to change some colors to match their brand. I think one way to improve the DX for all of us is to embrace CSS variables. That's why the library has switched to css variables!
All you want is to change the color of the progress bar? No problem

:root{
  // this is the default value below
  --toastify-color-progress-light: linear-gradient(
    to right,
    #4cd964,
    #5ac8fa,
    #007aff,
    #34aadc,
    #5856d6,
    #ff2d55
  );
}
Enter fullscreen mode Exit fullscreen mode

You can find the list of all exposed variables here

Thanks for reading. You can access the full release note here

Discussion (6)

Collapse
optimbro profile image
Rahul • Edited

Hi, I'm new to ReactJS, just practicing it but I want to use this with my simple function that fetches data from github users api.. This looks cool πŸ˜‡

const url = 'https://api.github.com/users

const fetchUsers = async () => {
      const response = await fetch(url);
// show error if network failed etc
      const usersData = await response.json();
// Show error if not found
      setUsers(usersData);
// Show success notification
    };

fetchUsers();
Enter fullscreen mode Exit fullscreen mode

So, how can I use it with above simple example... and how to use the promise feature with the same..

And I think you are the original author 😍

Thanks

Collapse
optimbro profile image
Rahul
  useEffect(() => {
    const fetchUsers = async () => {
      const fetchUrl = fetch(url);
      toast.promise(fetchUrl, {
        pending: 'Fetching data',
        success: 'Fetched data successfully πŸ‘Œ',
        error: 'Something went wrong 🀯',
      });
      const response = await fetchUrl;
      const usersData = await response.json();
      setUsers(usersData);
    };

    fetchUsers();
  }, []);
Enter fullscreen mode Exit fullscreen mode

So I achived working with promise with async await, I hope its good.

Collapse
fkhadra profile image
Fadi Khadra Author

Hey @optimbro actually, toast.promise return the provided promise. So you can await it directly. You can check this example codesandbox.io/s/inspiring-forest-...

Collapse
manoharreddyporeddy profile image
Manohar Reddy Poreddy

nice
pending to resolve, slow flip will be great to see

Collapse
fkhadra profile image
Fadi Khadra Author

Hey, what do you mean by "slow flip" ?

Collapse
manoharreddyporeddy profile image
Manohar Reddy Poreddy

in the attached img:

dev-to-uploads.s3.amazonaws.com/up...

  • pending - animation
  • then a flip (should be a bit slower)
  • resolved - animation