javascriptreactjs

How to wait until an HTML Element doesn't exist?


I'm working in ReactJS. What is the best way to find out when an element has been removed, and does not exist? I prefer to use latest MutationObserverAPI , unless ReactJs has library function to handle this. I can select the Element by Id # attribute.

https://stackoverflow.com/a/61511955/15435022

This is reference code to see when Element does not exist.

function waitForElm(selector) {
    return new Promise(resolve => {
        if (document.querySelector(selector)) {
            return resolve(document.querySelector(selector));
        }

        const observer = new MutationObserver(mutations => {
            if (document.querySelector(selector)) {
                observer.disconnect();
                resolve(document.querySelector(selector));
            }
        });

        // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });
}

Solution

  • Consider this parent/child component

    Parent:

    import React, { useState } from "react";
    import Child from "./Child";
    
    interface Props { }
    
    function Parent(props: Props) {
        const [showChild, setShowChild] = useState(false);
    
        function callback(id: number) {
            console.log(`Child ${id} removed from the dom`);
        }
    
        return (
            <div>
                <button onClick={() => setShowChild(!showChild)}>Show/Hide Child</button>
                {showChild && <Child callback={callback} id={123456} />}
            </div>
        );
    }
    
    export default Parent;
    

    Child:

    import React, { useEffect } from "react";
    
    interface Props {
        callback: (id: number) => void;
        id: number;
    }
    
    function Child(props: Props) {
        const { callback, id } = props;
    
        useEffect(() => {
            return () => {
                callback(id);
            };
        }, []);
    
        return (
            <div>
                {id}
            </div>
        );
    }
    
    export default Child;
    

    With this setup, the function "callback" would only fire once the child component is unmounted and removed from the dom. Note that the useEffect cleanup function fires any time a dependency changes in the dependency array, as well as if the component unmounts. For your case, if you have a useEffect with no dependencies, it should serve your needs!

    The MutationObserverApi works as well! My personal preference is to leverage useEffect, and if you have a specific component you're expecting to be removed from the dom, it's easier (at least in my mind) to have the code handling seeing if it unmounts/performing some action within the component itself!

    Resources: https://react.dev/reference/react/useEffect#connecting-to-an-external-system