I have the following embed code from infogram which is not rendering on my react app.
code looks as below:
<div class="infogram-embed" data-id="861ca70e-552c-4a4f-960a-4c7e7ff62881" data-type="interactive" data-title="Step by Step Charts"></div><script>!function(e,t,s,i){var n="InfogramEmbeds",o=e.getElementsByTagName("script")[0],d=/^http:/.test(e.location)?"http:":"https:";if(/^\/{2}/.test(i)&&(i=d+i),window[n]&&window[n].initialized)window[n].process&&window[n].process();else if(!e.getElementById(s)){var r=e.createElement("script");r.async=1,r.id=s,r.src=i,o.parentNode.insertBefore(r,o)}}(document,0,"infogram-async","https://e.infogram.com/js/dist/embed-loader-min.js");</script><div style="padding:8px 0;font-family:Arial!important;font-size:13px!important;line-height:15px!important;text-align:center;border-top:1px solid #dadada;margin:0 30px">Step by Step Charts<br>Infogram</div>
I am using a html parsing library for react which works perfectly fine in all other cases.
Any idea why this is not working?
Thanks
Not sure if this helps, here is how I made it work with React
https://jsfiddle.net/wonderwhy_er/4dt28xzL/6/
Or code
In HTML
<script>!function(e,t,s,i){var n='InfogramEmbeds',o=e.getElementsByTagName('script')[0],d=/^http:/.test(e.location)?'http:':'https:';if(/^\/{2}/.test(i)&&(i=d+i),window[n]&&window[n].initialized)window[n].process&&window[n].process();else if(!e.getElementById(s)){var r=e.createElement('script');r.async=1,r.id=s,r.src=i,o.parentNode.insertBefore(r,o)}}(document,0,"infogram-async","https://e.infogram.com/js/dist/embed-loader-min.js");</script>
<div id="app"></div>
In JS
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<div class="infogram-embed" data-id="861ca70e-552c-4a4f-960a-4c7e7ff62881" data-type="interactive" data-title="Step by Step Charts">
</div>
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
I moved script part away, it just requests a loader from Infogram and you do not need to do it inside of React render, so I just moved it to header of page or something.
You also have something else at the end of the embed which I remeved and it works. Check link.
Related
I want to integrate my react app to a 3rd party app which enables me to put a script that appends the elements into the html.
But it appears that it is not that straightforward in react. The script does not append the elements so my custom component does not appear on the page.
This is what I am trying to do ( but not a gist ):
function Snippet){
return (
<Wrapper>
<h1> Snippet 1</h1>
<script src="https://gist.github.com/xxxx/e4208e452e32e353b6076944c80a1058.js"></script>
</Wrapper>
)
}
Is there a way to do this with just react?
Hi Going back to this inquiry, I found an npm package that enables the embedding of github gist in a react component.
Following the implementation of the Gist Component in the package, we can also deploy the code programmatically instead of pasting the deployment script directly to the component and it will work just fine.
export default class DeployedComponent extends React.Component{
constructor(props){
super(props);
}
componentDidMount(){
(function(props,doc,elementName,id){
let jsElement;
if(doc.getElementById(id)){
return;
}
jsElement = doc.createElement(elementName);
jsElement.id = id;
jsElement.src= "deployment_script_src";
doc.getElementsByClassName("cb-deployment-wrapper")[0].appendChild(jsElement);
})(this.props, document,"script","script_id");
}
render(){
return (
<div className="w-100 cb-deployment-wrapper ">
</div>
);
}
}
I am building a ReactJS application and have a typeform which I embed to the middle of the page. Problem is that as soon as the Type-Form loads in the https://www.npmjs.com/package/#heyjobs/react-typeform-embed
Code:
class OverTheCounter extends Component {
render() {
return (
<div className="OtcContainer">
<div className="overTheCounterPage">
{/*<img src={image1} alt="HeaderImage" />
<h1 >Over the counter</h1>
</div>
<OtcIcon />
*/}
</div>
<ParallaxHeader />
<div className="typeForm">
<ReactTypeformEmbed
className="typeForm"
url="https://xxx.typeform.com/to/XXX"
/>
</div>
<OtcIcon />
<Footer />
</div>
);
}
}
export default OverTheCounter;
So for the react embed component you're using I can't comment or explain how it works. However I recently created and maintain a web components library (which from my tests works well with React).
You can install it with
npm install typeform-elements
And import the embed library into your apps entry point with:
import 'typeform-elements/dist/embed';
And finally use the component as so...
<typeform-standard url="{typeform_url}"></typeform-standard>
The embed component has a few attributes you can use and learn about here. And if things don't work, open an issue!
I'm writing a React-based application where one of the components receives its HTML content as a string field in props. This content is returned by an API call.
I need to:
Render this content as a standard HTML (i.e. with the styles applied)
Parse the content to see if the sections within the content have "accept-comments" tag and show a "Comment" button beside the section
For example, if I receive the HTML below, I should show the "Comment" button beside section with id "s101".
<html>
<head/>
<body>
<div id="content">
<section id="s101" accept-comments="true">Some text that needs comments</section>
<section id="s102">Some text that doesn't need comments</section>
</div>
</body>
</html>
Questions:
What would be the most efficient way to parse and render the HTML as the content can get a bit large, close to 1MB at times?
How can I ensure that React does not re-render this component as it will not be updated? I'd assume always return "false" from shouldComponentUpdate().
Things I've tried:
Render the HTML with "dangerouslySetInnerHTML" or "react-html-parser". With this option, cannot parse the "accept-comments" sections.
Use DOMParser().parseFromString to parse the content. How do I render its output in a React component as HTML? Will this be efficient with 1MB+ content?
This answer comes from Chris G's code in the comments. I used the code with different sizes of documents and it works well. Thanks Chris G!
Posting the code here in case the link link in the comments breaks.
The solution uses DOMParser to parse the HTML content provided by the API call and scans it to find the content that should include the "Comment" button. Here are the relevant parts.
import React from "react";
import { render } from "react-dom";
const HTML =
"<div><section but='yes'>Section 1</section><section>Section 2</section></div>";
class DOMTest extends React.Component {
constructor(props) {
super(props);
const doc = new DOMParser().parseFromString(HTML, "application/xml");
const htmlSections = doc.childNodes[0].childNodes;
this.sections = Object.keys(htmlSections).map((key, i) => {
let el = htmlSections[key];
let contents = [<p>{el.innerHTML}</p>];
if (el.hasAttribute("but")) contents.push(<button>Comment</button>);
return <div key={i}>{contents}</div>;
});
}
render() {
return <div>{this.sections}</div>;
}
}
const App = () => (
<div>
<DOMTest />
</div>
);
render(<App />, document.getElementById("root"));
I created a react component that I want to use twice(or more) inside my page, and I need to load a script tag for it inside the head of my page but just once! I mean even if I use the component twice or more in the page it should add the script tag just once in the head.
The Problem is that this script tag should be absolutely a part of the component and not statically inserted in the head of my page.
Can anyone help me to make the magic happens? Thanks a lot in advance!
You can give react-helmet a try for managing changes to your <head> from within React components.
In particular, you can check this example where rendering the same element four times only adds the script tag once.
For completeness, the relevant code from the example (although the interesting part is to see how it executes):
import { Helmet } from "react-helmet";
function ComponentWithHeader() {
return (
<div>
<div>Oh hi</div>
<Helmet>
<script src="fake-url.js" />
</Helmet>
</div>
);
}
const App = () => (
<div>
<ComponentWithHeader />
<ComponentWithHeader />
<ComponentWithHeader />
<ComponentWithHeader />
</div>
);
You can set the state of the parent component to keep in memory that the script is already added.
if (!this.state.scriptAdded) {
// Add script tag
this.setState({ scriptAdded: true });
}
I'm curious what's the best way to use a regular JavaScript library (not written as a React component) inside a React environment.
For example, let's say there's a JavaScript library that embeds a simple widget to my webpage. The instructions are as follows:
Include the loading tag in the header.
Embed the snippet anywhere you want.
In a normal webpage, I would do the following:
<head>
<script src="http://karaoke.com/source.js"></script>
</head>
<body>
<h1>Hello look at my cool widget library</h1>
<karaoke width="600" height="400" />
</body>
How do I achieve the same effect where I have a React component like this?
class MainView extends Component {
render() {
return (
<div>
<h1>I want to show my karaoke widget here, but how?</h1>
</div>
);
}
}
The main purpose of JSX is to feel like HTML. The main purpose of render in a React component is to render that "fake" (virtual) HTML. If your external widget is also a React component, the solution is straightforward:
class MainView extends Component {
render() {
return (
<div>
<h1>Hello look at my cool widget library</h1>
<Widget width="600" height="400" />
</div>
);
}
}
All you have to make sure is that the code above runs after your widget script is loaded (so the Widget component is present). The exact solution to this would depend on your build system.
If your external library is not a React component, then you cannot use a custom widget tag and you must render actual HTML.
The big trick is to not return from render but manually render ourselves after the widget initializes what it needs:
class MainView extends Component {
render() {
// don't render anything
return <div/>;
},
componentDidMount() {
// find the DOM node for this component
const node = ReactDOM.findDOMNode(this);
// widget does stuff
$(node).activateMyCoolWidget();
// start a new React render tree with widget node
ReactDOM.render(<div>{this.props.children}</div>, node);
}
});
Take a look at portals for more details.