71

I have a small problem. After requesting a data from a service I got an iframe code in response.

<iframe src="https://www.example.com/show?data..." width="540" height="450"></iframe>

I would like to pass this in as a props to my modal component and display it but when I simply {this.props.iframe} it in the render function it is obviously displaying it as a string.

What is the best way to display it as html in react or using JSX?

GDelsaux
  • 79
  • 2
  • 10
Kocur4d
  • 6,701
  • 8
  • 35
  • 53

3 Answers3

62

If you don't want to use dangerouslySetInnerHTML then you can use the below mentioned solution

var Iframe = React.createClass({     
  render: function() {
    return(         
      <div>          
        <iframe src={this.props.src} height={this.props.height} width={this.props.width}/>         
      </div>
    )
  }
});

ReactDOM.render(
  <Iframe src="http://plnkr.co/" height="500" width="500"/>,
  document.getElementById('example')
);

here live demo is available Demo

Cyril F
  • 1,842
  • 2
  • 19
  • 35
Dhaval Patel
  • 7,471
  • 6
  • 37
  • 70
  • it is not that I don't want to use it I am not 100% sure how it can go wrong. Your solution is clean I would just required me to parse the string to extract the values. – Kocur4d Nov 25 '15 at 14:42
  • 1
    as per my understand in React to use dangerouslySetInnerHTML is not a good practice and ya if you think my solution would be an answer then accept it – Dhaval Patel Nov 25 '15 at 15:57
  • 2
    thanks for this code.. this is better than using dangersoulySetHtml – John Dec 21 '16 at 06:50
  • 1
    @Dhaval Patel this solution is good, however, based on the question, this does not solve the problem - **After requesting a data from a service I got an iframe code in response** - seems iframe is a string, how to render it in this case? – Oleksandr T. Oct 06 '17 at 05:00
  • 1
    @AlexanderT.: can you please post some code what exactly you want to render – Dhaval Patel Oct 06 '17 at 06:40
  • @Dhaval Patel for instance, I get this string from server when I do `http://server.com/a` - ``, also I can get another result from `http://server.com/b` list so - ``, or `` - respose is always string, and I can't change response, how your solution will handle such case? My question related to base question *After requesting a data from a service I got an iframe code in response*. – Oleksandr T. Oct 06 '17 at 06:51
  • @AlexanderT. Ohh simply you can parse the response and manipulate your response to find the iframe from it. – Dhaval Patel Oct 06 '17 at 06:54
  • Please keep in mind this best practices as well: https://medium.com/@ebakhtarov/handling-of-iframes-in-react-f038be46ac24 – Custodio Mar 09 '18 at 17:31
  • Sems to depend on create-ceact-class: https://stackoverflow.com/a/46482477/5308983 – thinwybk Mar 29 '21 at 11:06
48

You can use property dangerouslySetInnerHTML, like this

const Component = React.createClass({
  iframe: function () {
    return {
      __html: this.props.iframe
    }
  },

  render: function() {
    return (
      <div>
        <div dangerouslySetInnerHTML={ this.iframe() } />
      </div>
    );
  }
});

const iframe = '<iframe src="https://www.example.com/show?data..." width="540" height="450"></iframe>'; 

ReactDOM.render(
  <Component iframe={iframe} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>

also, you can copy all attributes from the string(based on the question, you get iframe as a string from a server) which contains <iframe> tag and pass it to new <iframe> tag, like that

/**
 * getAttrs
 * returns all attributes from TAG string
 * @return Object
 */
const getAttrs = (iframeTag) => {
  var doc = document.createElement('div');
  doc.innerHTML = iframeTag;

  const iframe = doc.getElementsByTagName('iframe')[0];
  return [].slice
    .call(iframe.attributes)
    .reduce((attrs, element) => {
      attrs[element.name] = element.value;
      return attrs;
    }, {});
}

const Component = React.createClass({
  render: function() {
    return (
      <div>
        <iframe {...getAttrs(this.props.iframe) } />
      </div>
    );
  }
});

const iframe = '<iframe src="https://www.example.com/show?data..." width="540" height="450"></iframe>'; 

ReactDOM.render(
  <Component iframe={iframe} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"><div>
smac89
  • 39,374
  • 15
  • 132
  • 179
Oleksandr T.
  • 76,493
  • 17
  • 173
  • 144
  • 4
    What are the downsides to using this like this? `Dangerously` sounds... well... dangerous – Matt Weber Aug 02 '20 at 14:36
  • Use dangerouslySetInnerHTML only if you have good control over what you are "iframing", otherwise it will expose your users to a cross-site scripting (XSS) attack. – Donald Shahini Jun 09 '21 at 11:26
22

With ES6 you can now do it like this

Example Codepen URl to load

const iframe = '<iframe height="265" style="width: 100%;" scrolling="no" title="fx." src="//codepen.io/ycw/embed/JqwbQw/?height=265&theme-id=0&default-tab=js,result" frameborder="no" allowtransparency="true" allowfullscreen="true">See the Pen <a href="https://codepen.io/ycw/pen/JqwbQw/">fx.</a> by ycw(<a href="https://codepen.io/ycw">@ycw</a>) on <a href="https://codepen.io">CodePen</a>.</iframe>'; 

A function component to load Iframe

function Iframe(props) {
  return (<div dangerouslySetInnerHTML={ {__html:  props.iframe?props.iframe:""}} />);
}

Usage:

import React from "react";
import ReactDOM from "react-dom";
function App() {
  return (
    <div className="App">
      <h1>Iframe Demo</h1>
      <Iframe iframe={iframe} />,
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit on CodeSandbox:

https://codesandbox.io/s/react-iframe-demo-g3vst

Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154