Search code examples
javascriptreactjsdomiframereact-hooks

How to reliably get Iframe content body updates in react effect


I'm loading html into an iframe through srcDoc with the sandbox="allow-same-origin".

I notice that frameRef.contentDocument.body.innerHTML is empty even though the content displays. I set an effect to watch that property and it is always undefined.

How can I reliably get the body of the iframe's content and be able to watch it for changes?


Sandbox: https://codesandbox.io/s/bold-voice-ufp664

in the console if you do refNode.contentDocument.body.innerHTML, you get the correct output. But through react, it's undefined.

I tried setting effect hooks on specific properties like the innerHTML as well as the entire node object, no avail.

I tried using a regular ref, same results.

I expected to be able to get the body of the iframe and watch it for changes.


Solution

  • Use the onLoad event of the iframe element to set the state when the frame is ready.

    Edit confident-estrela-igmq8t

    Code:

    export default function App() {
      const [frameElement, setFrameElement] = React.useState(null);
      const [templateHtml, setTemplateHtml] = React.useState(null);
    
      const handleFrameElement = React.useCallback(e => {
        setFrameElement(e.target);
      }, []);
    
      React.useEffect(() => {
        setTimeout(() => setTemplateHtml(html), 1200);
      }, []);
    
      React.useEffect(() => {
        console.log(
          "HOOK ",
          frameElement?.contentDocument?.body?.innerHTML?.length
        );
      }, [frameElement]);
    
      return (
        <div>
          {templateHtml && (
            <iframe
              srcDoc={templateHtml}
              sandbox="allow-same-origin"
              onLoad={handleFrameElement}
            />
          )}
        </div>
      );
    }