We can simply use the ReactDOMServer. renderToString() to convert a react component to string and then set it to srcDoc attribute of iframe.
In React, developers use iframes to create either a sandboxed component or an application that is isolated from its parent component. In an iframe, when a piece of content is embedded from an external source, it is completely controlled by the source instead of the website it is embedded in.
To check if iframe is loaded or it has a content with JavaScript, we can set the iframe's onload property to a function that runs when the iframe is loaded. document. querySelector("iframe"). onload = () => { console.
If you want to include static html in ReactJS. You need to use html-loader plugin if you are using webpack to serve your react code. That is it. Now you can use static html files to load your html files in react.
TLDR;
If you're looking for a way to control the contents of an <iframe>
via React in a de-facto canonical way, Portals are the way to go.
And as with all things Portal: Once you establish a reference to an existing and mounted DOM node (in this case that would be the contentWindow of a given <iframe>
) and
create a Portal with it, its contents are also considered children of the «parent» virtual DOM, which means a shared (synthetic) event system, contexts and so on.
Please note that, for code brevity, the examples below make use of the Optional chaining operator, which as of this writing is not supported in all browsers.
Example: A functional React component including hooks:
// iframe.js
import React, { useState } from 'react'
import { createPortal } from 'react-dom'
export const IFrame = ({
children,
...props
}) => {
const [contentRef, setContentRef] = useState(null)
const mountNode =
contentRef?.contentWindow?.document?.body
return (
<iframe {...props} ref={setContentRef}>
{mountNode && createPortal(children, mountNode)}
</iframe>
)
}
Example: A React class component:
// iframe.js
import React, { Component } from 'react'
import { createPortal } from 'react-dom'
export class IFrame extends Component {
constructor(props) {
super(props)
this.state = {
mountNode: null
}
this.setContentRef = (contentRef) => {
this.setState({
mountNode: contentRef?.contentWindow?.document?.body
})
}
}
render() {
const { children, ...props } = this.props
const { mountNode } = this.state
return (
<iframe
{...props}
ref={this.setContentRef}
>
{mountNode && createPortal(children, mountNode)}
</iframe>
)
}
}
Usage:
import { IFrame } from './iframe'
const MyComp = () => (
<IFrame>
<h1>Hello Content!</h1>
</IFrame>
)
Further control, for example over an <iframe>
s <head>
contents, can easily be achieved as
this Gist shows.
There is also react-frame-component, a package that imho offers pretty much
everything you need when working with controlled <iframe>
s in React.
Caveats:
<iframe>
wants to programmatically control (as in deciding about) its contents in a React-ish way.<iframe>
complies with the Same-origin policy.<iframe src="https://www.openpgp.org/>
kind of scenario.Use cases (that I know of);
Adding a given set of CSS styles (or stylesheets) to a controlled <iframe>
:
As one comment author pointed out, managing styles between a parent application and the contents of a controlled <iframe>
can be quite tricky.
If you're lucky enough to have (a) dedicated CSS file(s) incorporating all necessary visual instructions for your <iframe>
, it might suffice to just
pass your IFrame
component a <link>
tag referencing said style(s), even though this is not the most standard compliant way to go about <link>
refs:
const MyComp = () => (
<Frame>
<link rel="stylesheet" href="my-bundle.css">
<h1>Hello Content!</h1>
</Frame>
)
In this day and age, however, and especially in a React world, most of the time, build setups create styles and stylesheets on the fly: Because they leverage meta-languages like SASS or even more involved solutions like CSS-in-JS stuff (styled-components, emotion).
This sandbox contains examples of how to integrate some of the more popular styling strategies with iframes in React.
This answer used to also give recipes with regards to versions of React prior to 16.3. At this point in time, however, I think it's safe to say that most of us are able to pull off a React version including Portals, and, to a lesser extent, hooks. If you're in need of solutions with regards to iframes and React versions < 16, hit me up, I'll gladly offer advice.
There is an easier solution if someone just wants to display small HTML inside the iframe.
<iframe src={"data:text/html,"+encodeURIComponent(content)}/>
The max length of content is 32768 characters.
There is also easy to use react-frame-component package which was mentioned in the accepted answer.
You can use srcdoc
attribute of iframe. It will work!
srcdoc: Inline HTML to embed, overriding the src attribute.
Read: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
This works too (not supported in IE).
const myHTML = <h1>Hello World</h1>
<iframe srcDoc={myHTML} />
More info here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe
Using the DOMParser constructor's parseFromString to parse the html is a little simpler than the accepted answer. Here is an example where the parsed html is retrieved from the DOMParser's generated document. If you're sending an element to the iframe, leave out the .body.innerText
part of the parseHtml
.
class SimpleIframe extends Component {
render() {
const parseHtml = html => new DOMParser().parseFromString(html, 'text/html').body.innerText;
return <iframe srcDoc={parseHtml(this.props.wholeHTMLDocumentString)} />;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With