Add Iframely to React

Known issue

React has its own virtual DOM and doesn't execute (eval) any inline scripts that go with HTML elements you add. Even when you use dangerouslySetInnerHTML. Even if that "dangerous" HTML is actually trusted to be safe. React considers that you expose youself to the risks of out-of-sync virtual DOM.

This said, React cannot support any JavaScript-based embeds out-of-the-box. It means you need a workaround for, say, Twitter, Instagram, Imgur, GitHub Gists, Iframely cards and lazy-loaded iFrames, and, well, Facebook itself.

Wheareas all iFrame-based embeds are absolutely fine and cause no DOM issues.

If you use native embed codes from publishers as-is with their varying script elements, we do not have a bullet-proof general fix for you. However, if you opt to rely on Iframely's iFrame helpers, this guide gives a solution on how to support all our embeds.

The solution

The fix is straightforward: Iframely offers a single external embed.js script that you need to deal with. It is served from our global CDN and is attached to all embeds that require scripting.

You may actually show all embeds just with embed.js by simply marking up your links as <a href='...' data-iframely-url></a>.

However, with dynamic React-powered pages, the initial load may be a little jerky that way, and so we also suggest iFrame-based approach as well. Read on.

Add embed.js to your page

In a simple form, it is just

<script src="//cdn.iframe.ly/embed.js" async></script>

See this gist to embed.js conditionally, only when there are embeds on your page that need it. If you use Custom CDN - please load embed.js from your own host.

Omit script

With your API calls, add &iframe=1 and &omit_script=1 as query-string parameters. It tells Iframely that you load embed.js script yourself. API will therefore return direct <iframe> element with proper attributes and sizing divs instead of our universal <a> embed.

Your React component

Add the following methods to your React component:

componentDidMount: function() {
    // This is required if you use pure embed.js approach
    // Or if you use lazy-loading of iFrames
    // It initiates the iFrame and adjusts its height if required
    window.iframely && iframely.load();
},

// Depending on your components, you may need to move iframely.load() 
// from `componentDidMount` to `componentDidUpdate`. Quote from React docs:
// "Do note that componentDidMount will however not be called on component updates"

getIframelyHtml: function() {
    // If you use embed code from API
    return {__html: this.iframelyEmbedHtmlCode};

    // Alternatively, if you use plain embed.js approach without API calls:
    // return {__html: '<a href="' + this.url + '" data-iframely-url></a>'};
    // no title inside <a> eliminates the flick

    // but getting actual HTML from our APIs is still recommended 
    // as it will have better sizing initially
},

render: function () {
    // `dangerouslySetInnerHTML` is safe,
    // Naming is meant to make sure you trust the source,
    // with &iframe=1&omit_script=1 - the source will be always be Iframely 
    return <div dangerouslySetInnerHTML={this.getIframelyHtml()} />
}

You may also opt to self-host embed.js script. It is available on GitHub and NPM.

Previous article: Instant Articles
Next article: Angular