Adding and Executing Script Tags in React Render
Returning and rendering script
tags in React components will definitely add them in the DOM but won’t really execute them. For example:
function Component(props) {
return (
<div>
<h1>Hello React!</h1>
<script src="htttps://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.production.min.js"></script>
<script>window.alert('Hello React!');</script>
</div>
);
}
The first script
tag won’t load the external script where as the second one won’t execute the inline script (alert
). But they’ll definitely be rendered in the DOM, you can fire up the dev tools and inspect elements.
The reason why the execution doesn’t happen is because internally React uses innerHTML
on the respective elements to actually set/inject/flush the changes into the DOM. The HTML5 spec specifies that user agents (browsers) must not execute the script
tags set via innerHTML
(more info at MDN).
So what do we do then ?
Create Scripts on Render and Add them to DOM with Vanilla JavaScript
When a component mounts (componentDidMount
for Class components) or renders (useEffect
in Functional component), we can create a script
element, set its src
or innerHTML
and then append it to the HTML document’s head
or body
.
useEffect(() => {
// componentDidMount() {}
const externalScript = document.createElement('script');
externalScript.src = '...';
externalScript.async = true;
document.head.append(externalScript);
const inlineScript = document.createElement('script');
inlineScript.innerHTML = '...';
document.body.append(inlineScript);
// componentWillUnmount() {}
return () => {
externalScript.remove();
inlineScript.remove();
};
}, []);
If you want you can throw the entire logic of generating the script element into a utility or helper function and then call that with minimal arguments.
Use a Third Party Library like Helmet that Does Exactly What We Did Above
react-helmet
takes plain HTML tags and outputs the same in document.head
(<head />
).
// After `npm i react-helmet`
import { Helmet } from 'react-helmet';
function Component(props) {
return (
<div>
<h1>Hello React!</h1>
<Helmet>
<script src="..."></script>
<script>...</script>
</Helmet>
</div>
);
}
Hope that helps!
This was great! Helmet did the trick for me. Thank you!