🐛(react) use uniqueId for modal portals

When a ModalProvider is mounted, it renders a div with an id which is use as
container to render modals through portals. But currently, if developer use
several CunninghamProvider across its application, a container with the same
id will be rendered several times that is weird. To prevent this kind of id
collision, we decide to generate a unique Id for each ModalProvider.

Resolve #352
This commit is contained in:
jbpenrath
2025-07-24 10:59:53 +02:00
committed by Jean-Baptiste PENRATH
parent 5b0d794217
commit ef8a225406
2 changed files with 7 additions and 6 deletions

View File

@@ -7,6 +7,7 @@ import React, {
ReactNode,
useContext,
useEffect,
useId,
useMemo,
useState,
} from "react";
@@ -112,6 +113,8 @@ export const ModalProvider = ({
modalParentSelector,
}: ModalProviderProps) => {
const [modals, setModals] = useState<ModalMap>({} as ModalMap);
const modalId = useId();
const modalParentId = `c__modals-portal-${modalId}`;
useEffect(() => {
ReactModal.setAppElement(".c__app");
@@ -160,10 +163,8 @@ export const ModalProvider = ({
confirmationModal: ModalHelper(ConfirmationModal),
messageModal: ModalHelper(MessageModal),
modalParentSelector: () => {
if (modalParentSelector) {
return modalParentSelector();
}
return document.getElementById("c__modals-portal")!;
if (modalParentSelector) return modalParentSelector();
return document.getElementById(modalParentId)!;
},
}),
[],
@@ -172,7 +173,7 @@ export const ModalProvider = ({
return (
<ModalContext.Provider value={context}>
{children}
<div id="c__modals-portal" />
<div id={modalParentId} />
{Object.entries(modals).map(([key, modal]) => (
<Fragment key={key}>{modal}</Fragment>
))}

View File

@@ -58,7 +58,7 @@ export type ModalProps = PropsWithChildren & {
export const Modal = (props: ModalProps) => {
/**
* This is a workaround to prevent the modal from rendering on the first render because if the modal is open on the
* first render, it will not be able to resolve document.getElementById("c__modals-portal") which is not rendered yet.
* first render, it will not be able to resolve document.getElementById(<MODAL_PARENT_ID>) which is not rendered yet.
*/
const [firstRender, setFirstRender] = React.useState(true);
useEffect(() => {