🐛(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:
committed by
Jean-Baptiste PENRATH
parent
5b0d794217
commit
ef8a225406
@@ -7,6 +7,7 @@ import React, {
|
|||||||
ReactNode,
|
ReactNode,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
|
useId,
|
||||||
useMemo,
|
useMemo,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
@@ -112,6 +113,8 @@ export const ModalProvider = ({
|
|||||||
modalParentSelector,
|
modalParentSelector,
|
||||||
}: ModalProviderProps) => {
|
}: ModalProviderProps) => {
|
||||||
const [modals, setModals] = useState<ModalMap>({} as ModalMap);
|
const [modals, setModals] = useState<ModalMap>({} as ModalMap);
|
||||||
|
const modalId = useId();
|
||||||
|
const modalParentId = `c__modals-portal-${modalId}`;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
ReactModal.setAppElement(".c__app");
|
ReactModal.setAppElement(".c__app");
|
||||||
@@ -160,10 +163,8 @@ export const ModalProvider = ({
|
|||||||
confirmationModal: ModalHelper(ConfirmationModal),
|
confirmationModal: ModalHelper(ConfirmationModal),
|
||||||
messageModal: ModalHelper(MessageModal),
|
messageModal: ModalHelper(MessageModal),
|
||||||
modalParentSelector: () => {
|
modalParentSelector: () => {
|
||||||
if (modalParentSelector) {
|
if (modalParentSelector) return modalParentSelector();
|
||||||
return modalParentSelector();
|
return document.getElementById(modalParentId)!;
|
||||||
}
|
|
||||||
return document.getElementById("c__modals-portal")!;
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[],
|
[],
|
||||||
@@ -172,7 +173,7 @@ export const ModalProvider = ({
|
|||||||
return (
|
return (
|
||||||
<ModalContext.Provider value={context}>
|
<ModalContext.Provider value={context}>
|
||||||
{children}
|
{children}
|
||||||
<div id="c__modals-portal" />
|
<div id={modalParentId} />
|
||||||
{Object.entries(modals).map(([key, modal]) => (
|
{Object.entries(modals).map(([key, modal]) => (
|
||||||
<Fragment key={key}>{modal}</Fragment>
|
<Fragment key={key}>{modal}</Fragment>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export type ModalProps = PropsWithChildren & {
|
|||||||
export const Modal = (props: ModalProps) => {
|
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
|
* 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);
|
const [firstRender, setFirstRender] = React.useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user