Brandon Brandon - 2 months ago 9
HTML Question

Creating a new DOM node instead of re-rendering

I'm using an iframe component that loads a cross-origin url passed down via

props
. Navigating the iframe to a new url via props pushes a new entry into the iframe's history, which hijacks the browser's 'back' button. This is expected behavior for cross-origin iframes whenever their src url changes.

Is it possible, then, to simply create a new iframe instead of changing the src? My assumption is that this would destroy whatever internal state the iframe had, thus preventing new entries into the 'back' button's history.

The iframe component (adapted from react-iframe):

// ETA: using React.Component instead of
// PureComponent yields the same back button behavior
const Iframe = class extends PureComponent {
render() {
return React.createElement('iframe', {
ref: 'iframe',
frameBorder: '0',
src: this.props.url,
sandbox: this.props.sandbox,
referrerpolicy: 'no-referrer',
target: '_parent',
allowFullScreen: this.props.allowFullScreen || false,
style: Object.assign(
{},
{
position: this.props.position || 'absolute',
display: this.props.display || 'block',
height: this.props.height || '100%',
width: this.props.width || '100%'
},
this.props.styles || {}
),
height: this.props.height || '100%',
width: this.props.width || '100%'
});
}
};


ETA: I am assuming that creating a new underlying iframe will prevent entries into history based on this answer, which reads:


don't change the src, just replace the old iframe with a new one?
No history states. Same functionality. Everyone wins.


<!doctype html>

<style> iframe {
width: 300px;
height:300px; } </style>

<script> var urls = ["http://bing.com", "http://google.com",
"http://duckduckgo.com"];

function next() {
if(urls.length==0) return;
var original = document.getElementsByTagName("iframe")[0];
var newFrame = document.createElement("iframe");
newFrame.src = urls.pop();
var parent = original.parentNode;
parent.replaceChild(newFrame, original); } </script>

<p>let's test some iframes</p> <button onclick="next()">next</button>
<iframe />

Answer Source

You should use the Component and not the PureComponent in such case, or instead - use the forceupdate method.

The PureComponent implements shouldComponentUpdate() with a shallow prop and state comparison, which caused your component to not re-render.