Create toasts from outside of React Components

mingming-ma

Mingming Ma

Posted on April 1, 2024

Create toasts from outside of React Components

This week, I submitted a PR to ChatCraft that added an alert function using the Standalone Toasts feature of Chakra UI. I previously used the useToast hooks, but I found that the Standalone Toasts are the solution when hooks can't be used. I'd like to share how I implemented it.

Standalone Toasts

Firstly, let's see the examples from Chakra UI document

import * as ReactDOM from 'react-dom/client'
import { createStandaloneToast } from '@chakra-ui/react'

const { ToastContainer, toast } = createStandaloneToast()

// render the ToastContainer in your React root
const rootElement = document.getElementById('root')
ReactDOM.createRoot(yourRootElement).render(
  <>
    <App />
    <ToastContainer />
  </>,
)

toast({
  title: 'An error occurred.',
  description: 'Unable to create user account.',
  status: 'error',
  duration: 9000,
  isClosable: true,
})
Enter fullscreen mode Exit fullscreen mode

At first glance, I found it a little confusing because it seems like we need to add the ToastContainer somewhere.

// render the ToastContainer in your React root
const rootElement = document.getElementById('root')
ReactDOM.createRoot(yourRootElement).render(
  <>
    <App />
    <ToastContainer />
  </>,
)

Enter fullscreen mode Exit fullscreen mode

Actually, if your project already has @chakra-ui/react installed, then we don't need to import it separately. What we need becomes to :


import { createStandaloneToast } from '@chakra-ui/react'

const { toast } = createStandaloneToast()

toast({
  title: 'An error occurred.',
  description: 'Unable to create user account.',
  status: 'error',
  duration: 9000,
  isClosable: true,
})
Enter fullscreen mode Exit fullscreen mode

How I did in the PR

//utils.ts
/**
 * Only meant to be used outside components or hooks
 * where useAlert cannot be used.
 */
import type { AlertArguments } from "../hooks/use-alert";
export const utilizeAlert = async () => {
  const { createStandaloneToast } = await import("@chakra-ui/react");
  const { toast } = createStandaloneToast();

  const info = ({ id, title, message }: AlertArguments) => {
    toast({
      id,
      title,
      description: message,
      colorScheme: "blue",
      status: "info",
      position: "top",
      isClosable: true,
      duration: 3000,
    });
  };

  const loading = ({ id, title, message }: AlertArguments) => {
    const fallbackId = new Date().toISOString();
    toast({
      id: id ?? fallbackId,
      title,
      description: message,
      colorScheme: "blue",
      status: "loading",
      position: "top",
      isClosable: true,
      duration: null,
    });
    return id ?? fallbackId;
  };

  const closeLoading = (id: string) => {
    toast.close(id);
  };

  return {
    info,
    loading,
    closeLoading,
  };
};
Enter fullscreen mode Exit fullscreen mode

As you can see, I wrap different kinds of toasts in the utilizeAlert function. Then we can show the alert by:

import { utilizeAlert } from "./utils";

const nonComponentFunction () {
    const { info , loading, closeLoading } = await utilizeAlert();

    //show info alert
    info({title: "this is info alert"})

    //show loading alert
    const alertId = loading({
      title: `Generating image, please wait.`,
    });

    //some stuff

    //close loading alert
    closeLoading(alertId);
}
Enter fullscreen mode Exit fullscreen mode

Standalone Toasts are a good design pattern that allows users to create toasts outside of a component. Sometimes it's good to have more options, and I think that's one of the reasons why Chakra UI is so popular. So that's it. I hope you found this helpful. Thanks for reading!

💖 💪 🙅 🚩
mingming-ma
Mingming Ma

Posted on April 1, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related