Daniel Kormos
Daniel Kormos

Reputation: 280

Close modal if another one is opened

Im trying to create a react Modal component from scratch. I would like to add the functionality of closing the modal when another one is opened.

I know the logic how to solve(i think i know), but cant implement it. My approach would be using context, where i store the current modal opened(currentModal) and if another one is opened then it would check if there is a currentModal and if so it would close it.

So far i have the modal component:

export function Modal({title, isOpen, children, onClose}){
 
    return(
        createPortal(
        <trds-modal class={isOpen ? 'opened': ''} onClick={onClose}>
            <trds-modal_container onClick={e => e.stopPropagation()}>
                <trds-modal_header>
                    <h2>{title}</h2>
                    <Icon icon="x" onClick={onClose} />
                </trds-modal_header>
                <trds-modal_body>
                    {children}
                </trds-modal_body>
            </trds-modal_container>
        </trds-modal>, document.body)
    )

}

Upvotes: 0

Views: 53

Answers (1)

Daniel Kormos
Daniel Kormos

Reputation: 280

i figured it out.

Created a context provider where i store the id of the current modal opened.

export function ModalContextProvider({children}){

    const [currentModalId, setCurrentModalId] = useState(null);

    return(

        <modalContext.Provider value={[currentModalId, setCurrentModalId]}>
            {children}
        </modalContext.Provider>

    )

}

then in the modal component i generate a uniqe id and set the context's currentModalId to that. And if the currentModalId changes then the modal checks if that equals to the modalId. If not, it calls the onClose function.

export function Modal({title, isOpen, children, onClose}){

    const modalId = useMemo(() => generateId(), []);

    const [currentModalId, setCurrentModalId] = useContext(modalContext);

    useEffect(() => {

        if(isOpen){
            setCurrentModalId(modalId);
        }

    }, [isOpen, setCurrentModalId, modalId]);

    useEffect(() => {

        if(currentModalId !== modalId) onClose();

    }, [currentModalId, modalId, onClose]);

    return(
        createPortal(
        <trds-modal class={isOpen ? 'opened': ''} onClick={onClose}>
            <trds-modal_container onClick={e => e.stopPropagation()}>
                <trds-modal_header>
                    <h2>{title}</h2>
                    <Icon icon="x" onClick={onClose} />
                </trds-modal_header>
                <trds-modal_body>
                    {children}
                </trds-modal_body>
            </trds-modal_container>
        </trds-modal>, document.body)
    )

}

I hope it help you as i couldn't find an approach to this problem. (maybe its not even an existing problem :D)

Upvotes: 1

Related Questions