DEV Community

fbcyborg
fbcyborg

Posted on

Retry loading an iframe until reachable in React

Hello everyone,

I am trying to implement an Iframe custom component which is loading a web page inside. Sometimes, the web page is not available and I want to implement a retry mechanism which continues until the page is available.

Here's the small piece of code I Implemented so far, without success.

App.js

import "./App.css";
import { CustomIFrame } from "./components/CustomIFrame.js";

function App() {
  return <CustomIFrame url="http://localhost/" />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

CustomIFrame.js

import React, { useRef, useState } from "react";

export const CustomIFrame = (props) => {
  const [isMounted, setIsMounted] = useState(false);
  const [iframeRef, setIframeRef] = useState();

  const handleIframeLoad = () => {
    console.log(iframeRef);
    // const anchors = iframeRef.contentWindow?.document.body.getElementsByTagName("a");
    // if(iframeRef.querySelector("...")){
      //     console.log('iFrame Loaded!');
      setIsMounted(true);
      // }
      // setTimeout(handleIframeLoad, 1000);
      console.log("iframe loaded!");
  };

//   console.log(iframeRef.current.children[0]);

  return (
    <div>
      <iframe
        title="my iframe"
        height="800"
        width="600"
        src={props.url}
        ref={setIframeRef}
        onLoad={handleIframeLoad}
      />
      {isMounted ? <div>The iframe content is mounted.</div> : ""}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Of course there is no retry mechanism yet in this code since I am not sure where to implement it. I was trying to add some retry logic inside the handleIframeLoad() where I would like to check if one of the component inside the iframe is rendered or not, and in case of failure, do a retry.

Could you please give some advice?

Top comments (1)

Collapse
 
fbcyborg profile image
fbcyborg

Hello everyone,

I changed a bit the component in the first post and I think it is okay now:

import React, { useState, useEffect } from "react";

export const CustomIFrame = (props) => {
  const [status, setStatus] = useState("");
  const [error, setError] = useState(null);
  const CHECK_INTERVAL = 10000;

  useEffect(() => {
    const fetchData = async () => {
      console.log(
        "Periodic check in progress - " + new Date() + " - Status: " + status
      );
      try {
        if (!status || status !== 200) {
          console.log("No data yet: fetching...");
          const res = await fetch(props.url);
          const response = res ? res : undefined;
          const newStatus = response && response.status ? response.status : "";
          console.log("newStatus: " + newStatus);
          setStatus(newStatus);
        }
      } catch (err) {
        console.error(err);
        setError(err.message);
      }
    };

    const interval = setInterval(fetchData, CHECK_INTERVAL); // Initial data fetching

    // Clean up the interval if the component unmounts
    return () => {
      clearInterval(interval);
      clearTimeout(fetchData);
    };
  }, [status, props.url]);

  return (
    <div>
      {status === 200 ? (
        <div>
          <iframe
            title="my iframe"
            id="myIframe"
            height="768"
            width="1366"
            src={props.url}
          />
        </div>
      ) : error ? (
        <div>Error: {error}</div>
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
};

Enter fullscreen mode Exit fullscreen mode

I'm not 100% about the solution I have found, but I hope someone can give me a feedback on that.