Home > Net >  How to wait until React in an iframe rendered it's content
How to wait until React in an iframe rendered it's content

Time:02-21

I am embedding a React app in an iframe. The app runs on the same domain as the iframe parent. I can wait for the iframe to load by using the onload event of the iframe like this:

<body>
<iframe id="frame" src="http://some/react/app"></iframe>

<script>
const frame = document.getElementById("frame");
frame.onload = () => {
  frame.querySelector("...");
}
</script>
</body>

However, the querySelector returns null if trying to query any element under the #reactRoot div created by react itself, probably because React hasn't finished rendering the contents of the app yet.

Using console.log to log the body of the iframe in the onload function displays the full body and all widgets of the React app in the console. I think this happens because the logged body element is only a reference and by the time I see it in the console, it's the React rendering already finished.

When using setTimeout like this, I can access the full body of the React app too because React rendering will be completed before the timeout function gets executed:

<body>
<iframe id="frame" src="http://some/react/app"></iframe>

<script>
const frame = document.getElementById("frame");
frame.onload = () => {
  setTimeout(() => console.log(frame.querySelector("...")), 1000);
}
</script>
</body>

Is there a more reliable way to wait until the React app in the iframe has finished rendering, or is waiting an arbitrary amount of time before accessing the iframe dodocument the only way to go? I don't like this solution very much because this solution will break as soon as a slow device needs more than one second for rendering the React app.

CodePudding user response:

this api may give you some help MessageChannel, and you can postMessage when the react root has been mounted

CodePudding user response:

You can poll for the existence of the expected element once the frame is loaded.

const startPolling = () => {
   if (frame.querySelector("...")) {
      console.log('react is ready')
      return 
   }
   setTimeout(startPolling, 1000)
}
frame.onload = () => {
   startPolling()
}
  • Related