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,
})
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 />
</>,
)
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,
})
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,
};
};
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);
}
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!
Top comments (0)