React: Script tag not working when inserted using dangerouslySetInnerHTML
Here's a bit of a dirty way of getting it done ,
A bit of an explanation as to whats happening here , you extract the script contents via a regex , and only render html using react , then after the component is mounted the content in script tag is run on a global scope.
var x = '<html><scr'+'ipt>alert("this.is.sparta");function pClicked() {console.log("p is clicked");}</scr'+'ipt><body><p onClick="pClicked()">Hello</p></body></html>';
var extractscript=/<script>(.+)<\/script>/gi.exec(x);
x=x.replace(extractscript[0],"");
var Hello = React.createClass({
displayName: 'Hello',
componentDidMount: function() {
// this runs the contents in script tag on a window/global scope
window.eval(extractscript[1]);
},
render: function() {
return (<div dangerouslySetInnerHTML={{__html: x}} />);
}
});
ReactDOM.render(
React.createElement(Hello),
document.getElementById('container')
);
React JS how to get script inside dangerouslySetInnerHTML executed
You can't because script tags are removed automatically for security.
The best way to work with javascript is to get the string separately and execute (or eval) it from componentWillMount or componentDidMount
class Page extends Component {
componentDidMount() {
const jsCode = `
console.log('hello world');
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'viewCart'
})
`;
new Function(jsCode)();
}
// you can do something else here
render() {
return (
<noscript />
);
}
}
You can obviously use any string. I presume you might be loading it from the server.
In the example above I used new Function()()
which is very similar to eval()
but works faster.
I used componentDidMount
so i'm certain the script executes after the view is shown. Another difference between Will and Did mount is that Will mount executes on both server and client sides of universal (isomorphic) apps, whereas Did mount will only execute on the client side of universal apps.
Script execution with dangerouslySetInnerHTML
The scripts that "will not execute" are script tags, like <script>
. See here for an example:
const html = `
<script>console.log('this does NOT run');<\/script>
<img src onerror="console.log('but this will')">
`;
const App = () => {
return <div dangerouslySetInnerHTML={{__html: html}} />;
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>
Javascript dynamically inserted later on: how to make it run?
If your are sure about HTML string content is safety and contains a string with valid HTML you can use Range.createContextualFragment() (executes scripts )
function App() {
const ref = useRef();
useEffect(() => {
/* convert your HTML string into DocumentFragment*/
const node = document.createRange().createContextualFragment(HTML);
ref.current.appendChild(node);
}, []);
return (
<div>
<h1>HTML String</h1>
<div>
<div ref={ref}></div>
</div>
</div>
);
}
See how script
content is executed on JavaScript console working example
If your are using class component
create ref
within class constructor, then update node content, I did it in componentDidMount
just for testing:
class App extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
componentDidMount() {
const node = document.createRange().createContextualFragment(HTML);
this.ref.current.appendChild(node);
}
render() {
return (
<div>
<h1>HTML String</h1>
<div>
<div ref={this.ref}></div>
</div>
</div>
);
}
}
see this working example
Related Topics
Want HTML Form Submit to Do Nothing
How to Use Greasemonkey to Selectively Remove Content from a Website
Setting CSS Value Limits of the Window Scrolling Animation
Make Function Wait Until Element Exists
Integrating Dropzone.Js into Existing HTML Form with Other Fields
How to Open a New Window and Insert HTML into It Using Jquery
How to Sort Elements by Numerical Value of Data Attribute
How to Prevent Page from Reloading After Form Submit - Jquery
How to Make Post Requests with the Formdata API
Input Type=File Show Only Button
Using Jquery How to Get Click Coordinates on the Target Element
How to Add Drop-Down List (<Select>) Programmatically
Check Ctrl/Shift/Alt Keys on 'Click' Event
JavaScript Checking for Null VS. Undefined and Difference Between == and ===
How to Change CSS :Root Color Variables in JavaScript
Implementing Pagination in Mongodb
How Might I Find the Largest Number Contained in a JavaScript Array