Closed julia-fix closed 7 months ago
To remove headless toasts without using toast.dismiss(), you can update the state of the toasts to remove the toast you want to dismiss. Since the toasts object is likely controlled by some state management system (such as React's state or a context), you can modify the state directly to remove the toast you want to dismiss.
export const PositionedToast = () => { const { toasts, handlers } = useToaster();
const dismissToast = (id) => {
handlers.dismiss(id);
};
return (
<div
style={{
position: 'static',
}}
>
{toasts.map((toast) => (
<div
key={toast.id}
className={classNames(style.toast, style[toast.type], toast.alignBottom && style.alignBottom)}
style={{
transition: 'all 0.5s ease-out',
opacity: toast.visible ? 1 : 0,
top: toast.position?.top,
left: toast.position?.left,
bottom: toast.position?.bottom,
right: toast.position?.right,
}}
onClick={() => dismissToast(toast.id)}
{...toast.ariaProps}
>
{toast.message}
</div>
))}
</div>
);
};
Try this i thought it should work
No, handlers
does not have dismiss
property. I ended up storing toast id in a local state and not rendering a toast if its id is in that array:
'use client';
import { useToaster } from 'react-hot-toast/headless';
import style from './PositionedToast.module.scss';
import classNames from 'classnames';
import { useState } from 'react';
export const PositionedToast = () => {
const { toasts } = useToaster();
const [deletedToasts, setDeletedToasts] = useState<string[]>([]);
return (
<div
style={{
position: 'static',
}}
>
{toasts.map((toast) => {
const dismissToast = () => {
setDeletedToasts([...deletedToasts, toast.id]);
};
return deletedToasts.includes(toast.id) ? null : (
<div
key={toast.id}
className={classNames(style.toast, style[toast.type], toast.alignBottom && style.alignBottom)}
style={{
transition: 'all 0.5s ease-out',
opacity: toast.visible ? 1 : 0,
top: toast.position?.top,
left: toast.position?.left,
bottom: toast.position?.bottom,
right: toast.position?.right,
}}
onClick={dismissToast}
{...toast.ariaProps}
>
{toast.message}
</div>
);
})}
</div>
);
};
@julia-fix As the handler object doesn't have the 'dismiss' method as of yet, you can manage it by shadowing the toast object.
Here is a example:
const useShadowToaster = () => {
const { toasts } = useToaster();
const [shadowToasts, setShadowToasts] = useState([]);
const [deletedToastsId, setDeletedToastsId] = useState([]);
useEffect(() => {
const newToasts = toasts.filter(toast => !deletedToastsId.includes(toast.id));
setShadowToasts(newToasts);
}, [toasts, deletedToastsId]);
const dismiss = (toastId) => {
setDeletedToastsId(prev => [...prev, toastId]);
setShadowToasts(prev => prev.filter(toast => toast.id !== toastId));
};
return {
toasts: shadowToasts,
handler: {
dismiss,
},
};
};
It is possible to use toast.dismiss
in headless mode. The problem in your example is that you are trying to call toast.dimiss
on the toast instance, and not the global import { toast } from "react-hot-toast/headless
.
I usually use the variable name t
when mapping over toasts to avoid this naming conflict. Here is a working demo.
Alternatively, you can rename the global toast object when importing to avoid the conflict:
import { toast as globalToast } from "react-hot-toast/headless"
globalToast.dismiss(id)
I use headless for showing toasts that I need to be positioned differently from normal ones. And the issue is that there is no toast.dismiss for headless toast. What is the way to remove it?
Here is my code: