GitHub

useToaster() API

The useToaster() hook provides you a headless system that will manage the notification state for you. This makes building your own notification system much easier.

It solves the following problems for you:

  • Built-in dispatch system with toast()
  • Handlers to pause toasts on hover
  • Automatically remove expired toasts
  • Support for unmount animations. Removal is delayed by 1s, but sets visible on the toast to false.

Importing from headless

You can import only the core of the library with react-hot-toast/headless. It won't include any styles, dependencies or custom components.

import { useToaster } from 'react-hot-toast/headless';

Be aware: react-hot-toast 2.0 adds support for custom render functions, an easier method to render custom notification components.

It's recommended to only have one <Toaster/> or useToaster() in your app at a time. If you need the current state without the handlers, you should use useToasterStore() instead.

Usage with React Native

Headless mode is perfectly suited to add notifications to your React Native app. You can check out this example.

Examples

Basic Example

import toast, { useToaster } from 'react-hot-toast/headless';
const Notifications = () => {
const { toasts, handlers } = useToaster();
const { startPause, endPause } = handlers;
return (
<div onMouseEnter={startPause} onMouseLeave={endPause}>
{toasts
.filter((toast) => toast.visible)
.map((toast) => (
<div key={toast.id} {...toast.ariaProps}>
{toast.message}
</div>
))}
</div>
);
};
// Create toasts anywhere
toast('Hello World');

Animated Example

Instead of mapping over visibleToasts we'll use toasts, which includes all hidden toasts. We animate them based on toast.visible. Toasts will be removed from 1 second after being dismissed, which give us enough time to animate.

You can play with the demo on CodeSandbox.

import { useToaster } from 'react-hot-toast/headless';
const Notifications = () => {
const { toasts, handlers } = useToaster();
const { startPause, endPause, calculateOffset, updateHeight } = handlers;
return (
<div
style={{
position: 'fixed',
top: 8,
left: 8,
}}
onMouseEnter={startPause}
onMouseLeave={endPause}
>
{toasts.map((toast) => {
const offset = calculateOffset(toast, {
reverseOrder: false,
gutter: 8,
});
const ref = (el) => {
if (el && typeof toast.height !== "number") {
const height = el.getBoundingClientRect().height;
updateHeight(toast.id, height);
}
};
return (
<div
key={toast.id}
ref={ref}
style={{
position: 'absolute',
width: '200px',
background: 'papayawhip',
transition: 'all 0.5s ease-out',
opacity: toast.visible ? 1 : 0,
transform: `translateY(${offset}px)`,
}}
{...toast.ariaProps}
>
{toast.message}
</div>
);
})}
</div>
);
};