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/
This answer explains the why behind this behavior.
Any approach to render the script
tag doesn't work as expected:
script
tag for external scriptsdangerouslySetInnerHTML
React DOM (the renderer for react on web) uses createElement
calls to render JSX into DOM elements.
createElement
uses the innerHTML DOM API to finally add these to the DOM (see code in React source). innerHTML
does not execute script tag added as a security consideration. And this is the reason why in turn rendering script
tags in React doesn't work as expected.
For how to use script
tags in React check some other answers on this page.
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):
componentWillMount () {
const script = document.createElement("script");
const scriptText = document.createTextNode("complex script with functions i.e. everything that would go inside the script tags");
script.appendChild(scriptText);
document.head.appendChild(script);
}
I created a React component for this specific case: https://github.com/coreyleelarson/react-typekit
Just need to pass in your Typekit Kit ID as a prop and you're good to go.
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;
According to Alex McMillan's solution, I have the following adaptation.
My own environment: React 16.8+, next v9+
// add a custom component named Script
// hooks/Script.js
import { useEffect } from 'react'
const useScript = (url, async) => {
useEffect(() => {
const script = document.createElement('script')
script.src = url
script.async = (typeof async === 'undefined' ? true : async )
document.body.appendChild(script)
return () => {
document.body.removeChild(script)
}
}, [url])
}
export default function Script({ src, async=true}) {
useScript(src, async)
return null // Return null is necessary for the moment.
}
// Use the custom compoennt, just import it and substitute the old lower case <script>
tag with the custom camel case <Script>
tag would suffice.
// index.js
import Script from "../hooks/Script";
<Fragment>
{/* Google Map */}
<div ref={el => this.el = el} className="gmap"></div>
{/* Old html script */}
{/*<script type="text/javascript" src="http://maps.google.com/maps/api/js"></script>*/}
{/* new custom Script component */}
<Script src='http://maps.google.com/maps/api/js' async={false} />
</Fragment>
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);
}
You can also use react helmet
import React from "react";
import {Helmet} from "react-helmet";
class Application extends React.Component {
render () {
return (
<div className="application">
<Helmet>
<meta charSet="utf-8" />
<title>My Title</title>
<link rel="canonical" href="http://example.com/example" />
<script src="/path/to/resource.js" type="text/javascript" />
</Helmet>
...
</div>
);
}
};
Helmet takes plain HTML tags and outputs plain HTML tags. It's dead simple, and React beginner friendly.