Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedding Reactjs in Remote Site iFrame

Updated for Bounty

I am currently using src="url" in my iframe to load the ReactApp which is not optimal for me as that will allow user to right-click and "Open In New Window".

The optimal solution which I'm looking for is to write my bundle.js into the iframe together with a or simliar solution. The src will remain as blank so user cannot conveniently right click to open in new window/tab.

I am exploring how to use React to make an embeddable widget so I got the following so far from googling. However, my doesn't render, and returns the following message.

Error Message [Error] Invariant Violation: Target container is not a DOM element.

I use create-react-app for my embeddable app and I have only 2 simple files.

index.js

import React from 'react';
import ReactDom from 'react-dom';
import App from './App';

ReactDom.render(
        <App />, document.getElementById('root')
)

App.js

import React, { Component } from 'react';

class App extends Component {
    render() {
        return (
            <div>This is an embedable widget</div>
            )
    }
}

export default App;

I created a test.js which will be called in the remote iframe with the simple codes below to generate the html, to include the js bundle, as well as the div with id.

This is the test.js

//Creates Div
var d = document.createElement("div");
document.body.appendChild(d);

//Creates iFrame
var n = document.createElement("iframe");
n.id = "microcom-frame";
n.style.width = "100%";
n.style.height = "100%";
n.style.background = "transparent";
n.style.position = "relative";
n.style.margin = 0;
n.style.border = "none";
n.style.overflow ="hidden";
n.style.display = "block";

//Append iFrame inside Div
d.appendChild(n);

//Write content to iFrame
n.contentWindow.document.open("text/html", "replace"), 
n.contentWindow.document.write("\n    <!doctype html>\n    <head><script src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></head>\n    <body><div id='root'></div></body>\n    </html>"), 
n.contentWindow.document.close();

Now on the remote site I just have the following script in the header to call my test.js above.

    <script>
      (function() {
  var d = document,
      h = d.getElementsByTagName('head')[0],
      s = d.createElement('script');

  s.type = 'text/javascript';
  s.async = true;
  s.src = 'http://localhost:3001/test.js';
  h.appendChild(s);
  
} )();
</script>

Now is this....

  • test.js loaded successfully
  • div created successfully
  • iframe created successfully
  • i can see bundle.js added in the header of iframe together with the div with id root

However, is not displaying.

Appreciate someone can bring me to the next step. I am using create-react-app to create my react files (that's the only way i learnt.)

like image 268
Someone Special Avatar asked Apr 03 '18 09:04

Someone Special


People also ask

Can we use iframe in Reactjs?

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 I remotely access my React app?

Simply pull up your device's browser and type in the IPv4 Address you copied down earlier followed by a colon and then the port number. The format should look something like the following: 555.55. 55.555:1234 once you hit enter, you should see your React App live on your mobile device!

How do I use iframe in React app?

The easiest way to insert an iframe into your React application is to use the dangerouslySetInnerHTML attribute. This attribute's value should be an object with __html key and the string HTML value. It's a fairly simple demonstration.


1 Answers

To satisfy the Same Origin policy (prevent CORS errors), set the <iframe>'s srcdoc attribute instead of trying to write to it.

n.srcdoc = "\n    <!doctype html>\n    <head><script src='http://localhost:3001/static/js/bundle.js' type='text/javascript'></script></head>\n    <body><div id='root'></div></body>\n    </html>";

As an added bonus, you can disable the right-click context menu with:

n.contentWindow.document.addEventListener("contextmenu", function(e){
    e.preventDefault();
    return false;
}, false);

This is completely useless as a security measure, but it's only there as a red herring. The page that shows when you open the frame on its own will not contain the content. Only do this if there's nothing in the iframe's page that the user will want to copy; it doesn't stop them from doing so, but it's really irritating if you do want to copy something.


Demo:

//Creates Div
var d = document.createElement("div");
document.body.appendChild(d);

//Creates iFrame
var n = document.createElement("iframe");
n.id = "microcom-frame";
n.style.width = "100%";
n.style.height = "100%";
n.style.background = "transparent";
n.style.position = "relative";
n.style.margin = 0;
n.style.border = "none";
n.style.overflow ="hidden";
n.style.display = "block";

//Append iFrame inside Div
d.appendChild(n);

//Write content to iFrame
n.srcdoc = "<!doctype html><html><head></head><body><div id='root'>Example content</div></body></html>";
like image 84
wizzwizz4 Avatar answered Sep 22 '22 07:09

wizzwizz4