Adding script tag in React / JSX

I have a relatively simple problem with trying to add inline scripts to a React component. What I still have:

'use strict'; import '../../styles/pages/people.scss'; import React, { Component } from 'react'; import DocumentTitle from 'react-document-title'; import { prefix } from '../../core/util'; export default class extends Component { render() { return ( <DocumentTitle title="People"> <article className={[prefix('people'), prefix('people', 'index')].join(' ')}> <h1 className="tk-brandon-grotesque">People</h1> <script src="https://use.typekit.net/foobar.js"></script> <script dangerouslySetInnerHTML={{__html: 'try{Typekit.load({ async: true });}catch(e){}'}}></script> </article> </DocumentTitle> ); } }; 

I also tried:

 <script src="https://use.typekit.net/foobar.js"></script> <script>try{Typekit.load({ async: true });}catch(e){}</script> 

None of the approaches execute the desired script. I guess this is a simple thing that I am missing. Can anybody help?

PS: Ignore foobar, I have a real identifier that I really don't like.

+188
javascript ecmascript-6 reactjs react-jsx
Dec 22 '15 at 21:38
source share
14 answers

Do you want to extract and execute the script again and again, each time this component is displayed, or only once when this component is mounted in the DOM?

Maybe try something like this:

 componentDidMount () { const script = document.createElement("script"); script.src = "https://use.typekit.net/foobar.js"; script.async = true; document.body.appendChild(script); } 

However, this is really useful only if the script you want to download is not available as a module / package. First, I would always:

  • Look for a package on npm
  • Download and install the package in my project ( npm install typekit )
  • import package where I need it ( import Typekit from 'typekit'; )

You probably installed both the react and react-document-title packages from your example, and Typekit is available on npm .

+267
Dec 22 '15 at 21:56
source share

In addition to the answers above, you can do this:

 import React from 'react'; export default class Test extends React.Component { constructor(props) { super(props); } componentDidMount() { const s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.innerHTML = "document.write('This is output by document.write()!')"; this.instance.appendChild(s); } render() { return <div ref={el => (this.instance = el)} />; } } 

Div is bound to this , and a script is injected into it.

Demo can be found at codesandbox.io

+46
Feb 08 '17 at 12:10
source share

My favorite way is to use React Helmet, which is a component that makes it easy to manipulate the head of a document the way you are probably used to.

eg

 import React from "react"; import {Helmet} from "react-helmet"; class Application extends React.Component { render () { return ( <div className="application"> <Helmet> <script src="https://use.typekit.net/foobar.js"></script> <script>try{Typekit.load({ async: true });}catch(e){}</script> </Helmet> ... </div> ); } }; 

https://github.com/nfl/react-helmet

+37
Dec 09 '17 at 21:35
source share

Alex Mcmillan's answer helped me the most, but didn't quite work on a more complex script tag.

I tweaked my answer a bit to come up with a solution for a long tag with various functions that additionally installed "src".

(For my use case, the script needed to live in my head, which is also reflected here):

  componentWillMount () { const script = document.createElement("script"); const scriptText = document.createTextNode("complex script with functions ie everything that would go inside the script tags"); script.appendChild(scriptText); document.head.appendChild(script); } 
+11
09 Oct '17 at 19:57
source share

If you need to have a <script> block in the SSR (server side rendering), the approach with componentDidMount will not work.

You can use the react-safe library react-safe . The code in React will be:

 import Safe from "react-safe" // in render <Safe.script src="https://use.typekit.net/foobar.js"></Safe.script> <Safe.script>{ 'try{Typekit.load({ async: true });}catch(e){}' } </Safe.script> 
+9
Jan 21 '18 at 19:53
source share

I created a React component for this particular case: https://github.com/coreyleelarson/react-typekit

You just need to transfer your ID Kitkit Kit as a props, and you're done.

 import React from 'react'; import Typekit from 'react-typekit'; const HtmlLayout = () => ( <html> <body> <h1>My Example React Component</h1> <Typekit kitId="abc123" /> </body> </html> ); export default HtmlLayout; 
+7
Dec 26 '16 at 3:45
source share

There is a very good workaround using Range.createContextualFragment .

 /** * Like React dangerouslySetInnerHTML, but also with JS evaluation. * Usage: * <div ref={setDangerousHtml.bind(null, html)}/> */ function setDangerousHtml(html, el) { if(el === null) return; const range = document.createRange(); range.selectNodeContents(el); range.deleteContents(); el.appendChild(range.createContextualFragment(html)); } 

This works for arbitrary HTML and also saves contextual information such as document.currentScript .

+3
Mar 02 '18 at 17:43
source share

You can use npm postscribe to load the script into the response component

 postscribe('#mydiv', '<script src="https://use.typekit.net/foobar.js"></script>') 
+2
Jun 13 '18 at 18:39
source share

I got document "undefined" when updating. I tried like this

 const MyComponent = () => { let script = React.createElement("script", { src: "https://.....js path", async: true, defer: true, crossorigin: "anonymous" }) return ( <div> {script} </div>) } 
0
May 7 '19 at 10:47
source share

for multiple scenarios use this

 var loadScript = function(src) { var tag = document.createElement('script'); tag.async = false; tag.src = src; document.getElementsByTagName('body').appendChild(tag); } loadScript('//cdnjs.com/some/library.js') loadScript('//cdnjs.com/some/other/library.js') 
0
20 '19 at 14:40
source share

I tried all the proposed solutions, but none of them worked. I am trying to embed this in a component but it is not loading. This is a banner from bannernack.com .

 <script type="text/javascript"> var bannersnack_embed = {"hash":"bxpien9pr","width":1190,"height":300,"t":1559889975,"userId":39254375,"responsive":true,"type":"html5"}; </script> <script type="text/javascript" src="//cdn.bannersnack.com/iframe/embed.js"></script> 
0
Jul 30 '19 at 11:16
source share
 componentDidMount() { const head = document.querySelector("head"); const script = document.createElement("script"); script.setAttribute( "src", "https://assets.calendly.com/assets/external/widget.js" ); head.appendChild(script); } 
0
Aug 30 '19 at 16:51
source share

You can find the best answer at the following link:

https://cleverbeagle.com/blog/articles/tutorial-how-to-load-third-party-scripts-dynamically-in-javascript

 const loadDynamicScript = (callback) => { const existingScript = document.getElementById('scriptId'); if (!existingScript) { const script = document.createElement('script'); script.src = 'url'; // URL for the third-party library being loaded. script.id = 'libraryName'; // eg, googleMaps or stripe document.body.appendChild(script); script.onload = () => { if (callback) callback(); }; } if (existingScript && callback) callback(); }; 
0
Sep 18 '19 at 10:24
source share

The decision depends on the scenario. As in my case, I had to load the calendar embed inside the react component.

It calendars the div and reads the data-url attribute from it and loads the iframe inside the specified div.

It’s good when you first load the page: first the div with data-url displayed. Then a calendar script is added to the body. The browser downloads and evaluates it, and we are all happy to go home.

The problem arises when you navigate and then return to the page. This time the script is still in the body, and the browser does not reload or overestimate it.

Fix:

  • In componentWillUnmount find and remove the script element. Then, on re mount, repeat the steps above.
  • Enter $.getScript . This is a great jQuery helper that accepts a script URI and a successful callback. After loading the script, it evaluates it and launches your callback. All I need to do is my componentDidMount $.getScript(url) . My render method already has a calendly div. And it works smoothly.
-one
Apr 04 '17 at 6:07
source share



All Articles