Bug: [React 19] Script tags not executing when embedded in components.
Embedding a <script> tag according to the documentation does not execute the contents of the script. It seems straightforward, but am I missing something?
React version: 19.1
Steps To Reproduce
- Set up a base React app.
- Include a
<script>tag anywhere in a component.
Example:
package.json
{
"main": "/index.js",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
},
"dependencies": {
"react": "19.1.0",
"react-dom": "19.1.0",
"react-scripts": "5.0.1",
"html-format": "1.1.7"
},
}
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
src/index.js
import { StrictMode, useEffect } from "react";
import { createRoot } from "react-dom/client";
function useScript(content) {
useEffect(() => {
const script = document.createElement("script");
script.innerHTML = content;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, [content]);
}
function App() {
// This works
useScript("console.log('Hello from hook!');");
// Do not work:
return (
<>
{/* Inline script */}
<script>console.log("Hello from inline script!");</script>
{/* Dangerous inline script */}
<script
dangerouslySetInnerHTML={{
__html: "console.log('Hello from dangerous inline script!');",
}}
></script>
{/* External script */}
<script
src="https://cdn.jsdelivr.net/npm/@tsparticles/[email protected]/tsparticles.confetti.bundle.min.js"
onLoad={() =>
setTimeout(() => confetti({ particleCount: 50, spread: 360 }), 1000)
}
></script>
<span>Hello world!</span>
</>
);
}
const root = createRoot(document.getElementById("root"));
root.render(
<StrictMode>
<App />
</StrictMode>
);
So, creating a script procedurally with a hook is fine, but adding a script tag of any type does not execute its contents.
The current behavior
The <script> tag gets embedded in the HTML, but its contents don't run for either inline or external scripts.
The expected behavior
Execute the contents of the <script> as specified.
can you please assign me this issue?
https://github.com/facebook/react/blob/4a9df08157f001c01b078d259748512211233dcf/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L462-L481
react/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Lines 462 to 481 in 4a9df08 case 'script': { // Create the script via .innerHTML so its "parser-inserted" flag is // set to true and it does not execute const div = ownerDocument.createElement('div'); if (DEV) { if (enableTrustedTypesIntegration && !didWarnScriptTags) { console.error( 'Encountered a script tag while rendering React component. ' + 'Scripts inside React components are never executed when rendering ' + 'on the client. Consider using template tag instead ' + '(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).', ); didWarnScriptTags = true; } } div.innerHTML = '
Ah, so it's SSR only? This section of the docs gave me the impression that it works during any render. It matches my use case for my SPA.
Hi š, thank you for reporting this issue.
Iād love to contribute and help resolve it. Before I begin, could you please confirm if the issue is still reproducible on the latest version of React?
Looking forward to your guidance š
@ZunedKhan07 Hello!
I've tried the above example with the latest version 19.1.1 and also 19.2.0-canary-eaee5308-20250728. Neither of these work with my setup.
Having same issue. We should either make this work client-side or update the documentation here: https://react.dev/reference/react-dom/components/script
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
bump
Just a small update. I've been playing with this a bit longer after noticing that the docs now indicate the script tag needs an async prop. I found that the presence of an onLoad handler breaks the script when the special rendering behavior kicks in.
This works:
export default function App() {
setTimeout(() => confetti({ particleCount: 50, spread: 360 }), 1000);
return (
<script
async
src="https://cdn.jsdelivr.net/npm/@tsparticles/[email protected]/tsparticles.confetti.bundle.min.js"
/>
);
}
But this does not:
export default function App() {
setTimeout(() => confetti({ particleCount: 50, spread: 360 }), 1000);
return (
<script
async
src="https://cdn.jsdelivr.net/npm/@tsparticles/[email protected]/tsparticles.confetti.bundle.min.js"
onLoad={() => console.log("Loaded")}
/>
);
}
With the onLoad handler set, the confetti function is undefined after the timeout.
React 19.2.0