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()
}