Display Toast at the Top Over the Portal-Based Modal.
I created the Modal as follows using a Portal.
//Portal.tsx
export const Portal = ({ containerId = "portal", children }: PortalProps) => {
const [container] = useState(() => {
const el = document.createElement("div");
el.id = containerId;
return el;
});
useEffect(() => {
document.body.appendChild(container);
return () => {
document.body.removeChild(container);
};
}, [container]);
return createPortal(children, container);
};
I have declared your toast in the Modal, and similarly, I have also declared it in app.tsx.
//Modal.tsx
import { ToastContainer } from "react-toastify";
<Portal containerId={`modal-${portalId}`}>
<ModalContext.Provider value={{ onClose }}>
<dialog
ref={dialogRef}
onClick={handleBackdropClick}
>
<div
className={classNames("popup-container", className)}
>
<div className={"popup-area"}>{children}</div>
</div>
<ToastContainer />
</dialog>
</ModalContext.Provider>
</Portal>
//App.tsx
<QueryClientProvider client={queryClient}>
<ToastContainer />
</QueryClientProvider>
I want to display a toast at the top even within a Portal, so I've defined the toast both inside the Portal and in app.tsx.
However, while the toast does appear at the top inside the portal, it fails to execute when I attempt to trigger the toast- displaying logic after closing the portal. Since the portal unmounts, the toast also does not mount.
In other words, while the toast can be displayed on top of either the Portal or app.tsx, there is a challenge in displaying the toast when the parent component unmounts.
Even when the toast is rendered within a portal, it does not appear above the modal created by another portal, and the toast does not persist as expected.
How can I resolve this issue?
The image below shows the state when the toast is not mounted inside the modal defined in the Portal.
The image below shows the toast when declared inside the Modal. However, in this case, it is not possible to display the toast after the modal is closed.
Same thing facing, is there any fix?
Update: I have got my fix.
this is my toast showing code
toast.promise(promise, {
pending: "Promise is pending",
success: "Promise resolved 👌",
error: "Promise rejected 🤯",
},
{ containerId: "dialog" }
);
and this is my modal
<dialog
ref={dialogRef}
className="w-md lg:w-xl p-8 rounded-xl shadow-lg fixed inset-0 m-auto max-w-2xl max-h-fit"
>
<p className="text-lg text-primary">Help & Support</p>
<div className="flex flex-col md:flex-row space-x-0 md:space-x-4">
<div className="flex-1 flex flex-col items-start mt-4">
<label htmlFor="nameBox">Name</label>
<input className="input-primary mt-2" type="text" id="nameBox" />
</div>
<div className="flex-1 flex flex-col items-start mt-4">
<label htmlFor="emailBox">Email</label>
<input className="input-primary mt-2" type="email" id="emailBox" />
</div>
</div>
<div className="flex flex-col items-start mt-4">
<label htmlFor="subjectBox">Subject</label>
<input className="input-primary mt-2" type="text" id="subjectBox" />
</div>
<span className="block mt-4"></span>
<div className="flex flex-col items-start">
<label htmlFor="descriptionBox">Please describe your problem</label>
<textarea
className="input-primary resize-none mt-2"
rows={6}
id="descriptionBox"
></textarea>
</div>
<span className="block mt-16"></span>
<div className="flex flex-row justify-end space-x-2">
<button
className="button-secondary"
onClick={() => dialogRef.current.close()}
>
Cancel
</button>
<button
className="button-primary"
onClick={() => sendHelpAndSupport()}
>
Send
</button>
</div>
<ToastContainer containerId="dialog" />
</dialog>
Hi, this isn't actually an issue with react-toastify but rather an issue with the way top-layer works.
That being said we have issue #959 that talks about this and has a workable fix for while we wait for the platform to update.