React - dangerouslySetInnerHTML - determine when element is done loading

1k Views Asked by At

I am trying to use the following jsx:

<div dangerouslySetInnerHTML={{__html: html}}/>

Where html is an embedded tweet, reddit post, etc.

Is there a way to determine when the html in this div is done loading? I wanted to use a progress wheel to render until then.

Here is an example of the html for twitter:

<blockquote class="twitter-tweet" > <p lang="en" dir="ltr"> I’m Bowser!!!<a href="...">@supermariomovie</a> <a href="...">pic.twitter.com/wr9KRX9syE</a></p>&mdash; Jack Black (@jackblack) <a href="...">October 11, 2022</a> </blockquote> <script async src="..." charset="utf-8"></script>
1

There are 1 best solutions below

4
David On

I don't know what your API data looks like or how you are calling the data but you could write an async function inside a useEffect hook. That in combination with an isLoading useState hook you could choose what to display. Set isLoading to true by default and then set it to false after your async function finishes. Then in the JSX you can use that state to conditionally display the data or a loading wheel.

const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
    const dataCallFunction = async () => {
       // await api call
       setIsLoading(false);
    }
    dataCallFunction();
}, []);

{isLoading ? <LoadingComponent /> : <div dangerouslySetInnerHTML={{__html: html}}/>}

EDIT: If you want to check if something in the document has finished loading you could do something like this.

const [playLoadAnimation, setPlayLoadAnimation] = useState(false);
useEffect(() => {
    const onPageLoad = () => {
        setPlayLoadAnimation(true);
    };

    if (document.readyState === "complete") {
      onPageLoad();
    } else {
      window.addEventListener("load", onPageLoad);
      // Remove the event listener when component unmounts
      return () => window.removeEventListener("load", onPageLoad);
    }
  }, []);
{playLoadAnimation && <LoadingIndicator />}
{!playLoadAnimation && <div dangerouslySetInnerHTML={{__html: html}}/>}

Credit to Rob Cary for this solution