Skip to content

Display Toast at the Top Over the Portal-Based Modal. #1220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
YoonJeongLulu opened this issue Mar 12, 2025 · 2 comments
Open

Display Toast at the Top Over the Portal-Based Modal. #1220

YoonJeongLulu opened this issue Mar 12, 2025 · 2 comments

Comments

@YoonJeongLulu
Copy link

YoonJeongLulu commented Mar 12, 2025

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.

Image

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.

Image
@diukawsar
Copy link

diukawsar commented Mar 24, 2025

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>

@Link2Twenty
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants