Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set iframe content of a react component

People also ask

How do I render a component in an iframe in React?

We can simply use the ReactDOMServer. renderToString() to convert a react component to string and then set it to srcDoc attribute of iframe.

How do I use iframe in React?

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.

How do you check if iframe is loaded React?

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.

HOW include HTML file in react JS?

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;

Edit react-iframe-examples

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:

  • This answer only addresses use cases, where the owner of a given <iframe> wants to programmatically control (as in deciding about) its contents in a React-ish way.
  • This answer assumes, that the owner of an <iframe> complies with the Same-origin policy.
  • This answer is not suited to track how and when external resources are loaded in an <iframe src="https://www.openpgp.org/> kind of scenario.
  • If accessibility is something you care about, you should give your iframes meaningful title attributes.

Use cases (that I know of);

  • The OP's use case: Ads and the need to control how and when those can access a safely scoped element on your website.
  • Embeddable third-party widgets.
  • My use case (and hence my somewhat informed stance on the matter): CMS UI's, where you want to enable users to preview scoped CSS styles, including applied media queries.

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.

Edit react-iframe-examples

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)} />;
    }
}