From 334d0ef92adbbbc0288d69b0f327f825b4d17171 Mon Sep 17 00:00:00 2001 From: Ryan Seddon Date: Sat, 31 Dec 2022 14:19:20 +1100 Subject: [PATCH] Rely on DOMContentLoaded instead of onload (#207) * Rely on DOMContentLoaded instead of onload onload event will delay if downloading external resources when really all we need to know is if the initialContent has rendered without worry about external resources being downloaded Fallback to setInterval if DOMContentLoaded fails --- .eslintrc | 1 + example/app.jsx | 53 ++++++++++++++++++++++++++++++++++++---------- example/index.html | 10 +++++---- src/Frame.jsx | 28 ++++++++++++++++++------ webpack.config.js | 5 +++++ 5 files changed, 76 insertions(+), 21 deletions(-) diff --git a/.eslintrc b/.eslintrc index 81b4d16..ea38f6e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -14,6 +14,7 @@ "parser": "babel-eslint", "rules": { "react/forbid-prop-types": "off", + "react/prop-types": [0, { "ignore": ["children"]}], "no-underscore-dangle": "off" } } diff --git a/example/app.jsx b/example/app.jsx index fc815d4..d49de3d 100644 --- a/example/app.jsx +++ b/example/app.jsx @@ -2,7 +2,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import Frame from '../src'; -var styles = { +const styles = { border: '1px solid', width: '100%', height: '100%' @@ -10,7 +10,7 @@ var styles = { const Header = ({ children }) =>

{children}

; -const Content = ({ children }) =>
{children}
+const Content = ({ children }) =>
{children}
; const App = () => (
@@ -21,15 +21,46 @@ const App = () => (
); -ReactDOM.render(, document.querySelector('#example1')); - -const Foobar = () => ( - {'*{color:red}'} - }> -

Frame example of wrapping component

-

This is also showing encapuslated styles. All text is red inside this component.

- +ReactDOM.render( + + + , + document.querySelector('#example1') ); +const Foobar = () => { + const [toggle, updateToggle] = React.useState(false); + return ( + {'*{color:red}'}}> +

Frame example of wrapping component

+

+ This is also showing encapuslated styles. All text is red inside this + component. +

+ {toggle &&

Hello

} + + + ); +}; + ReactDOM.render(, document.querySelector('#example2')); + +const ExternalResources = () => { + const initialContent = ` + + + +
`; + + return ( + +

External Resources

+

+ This tests loading external resources via initialContent which can + create timing issues with onLoad and srcdoc in cached situations +

+ + ); +}; + +ReactDOM.render(, document.querySelector('#example3')); diff --git a/example/index.html b/example/index.html index 26f8a30..696a736 100644 --- a/example/index.html +++ b/example/index.html @@ -7,11 +7,12 @@ * { color: blue; } - section { - display: flex; + iframe { + width: 100%; } - section div { - flex: 1; + section { + display: grid; + grid-template-columns: repeat(2, 1fr); } @@ -21,6 +22,7 @@

<Frame /> examples

+
diff --git a/src/Frame.jsx b/src/Frame.jsx index 767362a..ae88480 100644 --- a/src/Frame.jsx +++ b/src/Frame.jsx @@ -44,17 +44,22 @@ export class Frame extends Component { this._isMounted = true; const doc = this.getDoc(); - if (doc && doc.readyState === 'complete') { - this.forceUpdate(); - } else { - this.nodeRef.current.addEventListener('load', this.handleLoad); + + if (doc) { + this.nodeRef.current.contentWindow.addEventListener( + 'DOMContentLoaded', + this.handleLoad + ); } } componentWillUnmount() { this._isMounted = false; - this.nodeRef.current.removeEventListener('load', this.handleLoad); + this.nodeRef.current.removeEventListener( + 'DOMContentLoaded', + this.handleLoad + ); } getDoc() { @@ -81,9 +86,19 @@ export class Frame extends Component { }; handleLoad = () => { - this.setState({ iframeLoaded: true }); + clearInterval(this.loadCheck); + // Bail update as some browsers will trigger on both DOMContentLoaded & onLoad ala firefox + if (!this.state.iframeLoaded) { + this.setState({ iframeLoaded: true }); + } }; + // In certain situations on a cold cache DOMContentLoaded never gets called + // fallback to an interval to check if that's the case + loadCheck = setInterval(function loadCheckCallback() { + this.handleLoad(); + }, 500); + renderFrameContents() { if (!this._isMounted) { return null; @@ -130,6 +145,7 @@ export class Frame extends Component { delete props.contentDidMount; delete props.contentDidUpdate; delete props.forwardedRef; + return (