I have a relatively straightforward issue of trying to add inline scripting to a React component. What I have so far:
'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 have also tried:
<script src="https://use.typekit.net/foobar.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
Neither approach seems to execute the desired script. I'm guessing it's a simple thing I'm missing. Can anybody help out?
PS: Ignore the foobar, I have a real id actually in use that I didn't feel like sharing.
Further to the answers above you can do this:
The div is bound to
this
and the script is injected into it.Demo can be found on codesandbox.io
Solution depends on scenario. Like in my case, I had to load a calendly embed inside a react component.
Calendly looks for a div and reads from it's
data-url
attribute and loads an iframe inside the said div.It is all good when you first load the page: first, div with
data-url
is rendered. Then calendly script is added to body. Browser downloads and evaluates it and we all go home happy.Problem comes when you navigate away and then come back into the page. This time the script is still in body and browser doesn't re-download & re-evaluate it.
Fix:
componentWillUnmount
find and remove the script element. Then on re mount, repeat the above steps.$.getScript
. It is a nifty jquery helper that takes a script URI and a success callback. Once the script it loaded, it evaluates it and fires your success callback. All I have to do is in mycomponentDidMount
$.getScript(url)
. Myrender
method already has the calendly div. And it works smooth.If you need to have
<script>
block in SSR (server-side rendering), an approach withcomponentDidMount
will not work.You can use
react-safe
library instead. The code in React will be:Do you want to fetch and execute the script again and again, every time this component is rendered, or just once when this component is mounted into the DOM?
Perhaps try something like this:
However, this is only really helpful if the script you want to load isn't available as a module/package. First, I would always:
npm install typekit
)import
the package where I need it (import Typekit from 'typekit';
)This is likely how you installed the packages
react
andreact-document-title
from your example, and there is a Typekit package available on npm.The answer Alex Mcmillan provided helped me the most but didn't quite work for a more complex script tag.
I slightly tweaked his answer to come up with a solution for a long tag with various functions that was additionally already setting "src".
(For my use case the script needed to live in head which is reflected here as well):
There is a very nice workaround using
Range.createContextualFragment
.This works for arbitrary HTML and also retains context information such as
document.currentScript
.