Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load css provided by webpack inside an IFrame created using "react-frame-component" library?

I'm trying to render my React component inside an iframe. I got it to work by using the library "react-frame-component". The problem is that the styles are loaded outside the iframe, at the end of "head" element. I want to change it to be loaded inside the "head" of "iframe" element. I'm using Webpack to generate the bundles with JS and CSS included and I saw that I can change where "style-loader" will load the styles by setting the option "insertInto", but this is throwing an error:

Uncaught Error: Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.

This is my React component:

import Frame from 'react-frame-component'
...
ReactDOM.render(
  <Frame id="someId">
    <Provider store={Store.get()}>
      <Container/>
    </Provider>,
  </Frame>,
  document.body
);

This is my "style-loader" in Webpack configuration:

{
  loader: 'css-loader',
  options: {
    insertInto: () => document.querySelector("#someId"),
  },
}

I think the problem is that the component was not rendered when webpack tried to include the styles. How to solve this?

like image 501
Sandro Simas Avatar asked May 07 '18 02:05

Sandro Simas


People also ask

How do I get the iframe content 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.

Can you use iframes 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 iframe is loaded or not in React?

To detect when the iFrame has finished loading, we need to add an event listener to the iFrame, and we need to return the removeEventListener function to remove the event listener if our component unmounts.


1 Answers

You would need to load the styles into a temporary element as placeholder, and then use Javascript to clone those styles into the new frame.

// index.html
...
<div id="dynamic-styles"></div>
...
// webpack.config.js
...
{
  loader: 'css-loader',
  options: {
    insertInto: () => document.getElementById("dynamic-styles"),
  },
}
...
// some.js
...

const stylesContainer = document.getElementById('dynamic-styles');
const frame = document.getElementById('someID');
const frameHead = frame.contentWindow.document.head;

[...stylesContainer.children].forEach(styleNode => {
  const newStyle = document.createElement('style');
  newStyle.textContent = styleNode.textContent;

  frameHead.appendChild(newStyle);
});

I haven't tested the above snippet but I know the concept works. I feel it gets the point across.

There may be a better way to do this but I haven't looked into it enough to figure it out yet. It'd be nice to be able to get webpack to make separate style bundles so that each configured frame could just automatically lazy load it's own dedicated bundled css

like image 55
AlexMorley-Finch Avatar answered Sep 22 '22 13:09

AlexMorley-Finch