4

I was wondering of I can create a script element using react, something like:

var reactScriptElement = React.createElement('script', {src: "d.js"});
ReactDOM.render(reactScriptElement, document.getElementById('button'));

But, the script is not run by the browser. However, doing it the native way, does seems to run it:

var script = document.createElement('script');
script.src = "./d.js";
var div = document.getElementById('button');
div.appendChild(script);

So, is it a bug, by design, or something I am doing wrong?

Edit: This is not a duplicate. The issue here is the difference between the two, why they are not acting the same.

Daniel Rahamim
  • 285
  • 2
  • 18
  • Possible duplicate of [Adding script tag to React/JSX](http://stackoverflow.com/questions/34424845/adding-script-tag-to-react-jsx) – Chris Dec 06 '16 at 07:48
  • Definietly not. The issue here is the difference between the two, why they are not acting the same. – Daniel Rahamim Dec 06 '16 at 09:25

2 Answers2

2

The difference is that the react version never gets inserted into the real Browser DOM Ast a so-called shallow copies of the react vdom does get into the DOM the original behavior gets not used because its a reference to a script at another place in the realDOM the dom doesn't know that this referenced copy got inserted as it is only aware of the original referenced dom node that is not inserted.

A Little Demo of whats happening in details note that the escaped version of the script end tag is needed to prevent browser parsing bugs when this code gets used on a single page

<div id="root"></div>
<script>
const el = document.getElementById('root')
const script =`<script src=d.js></${'script'}>`
console.log(script)
el.innerHTML= script
</script>

when I set the innerHTML with a tag it doesn't get executed while it is inserted into the dom. when the script would be in an extra file, not a script tag it could use innerHTML = '<script src=d.js></script>' and still will not get executed by the dom because of the insertion method innerHTML that is used to set it on the object.

scripts get executed on insert script insert don't get detected when directly setting the dom without dom API. That's how the dom parser works.

frank-dspeed
  • 942
  • 11
  • 29
0

Can't confirm this but I think you need to pass a React component instead of react element. That's why it won't work.

class reactScriptElement extends React.Component {
  ...
  componentWillMount() {
    const script = document.createElement("script");
    script.src = "d.js";
    document.body.appendChild(script);
  }
  ...
}

ReactDOM.render(reactScriptElement, document.getElementById('button'));

Usually React.createElement is used to return from render() method of a react component. Your way of creating element won't work because you're passing an element instead of component.

Correct usage of React.createElement()-

class App extends React.Component {
  ...
  render() {
    return React.createElement(MyLabel, {label: "Here is the label prop"},
      React.createElement("div", {},
        React.createElement("input", {type: "text", value: "And here is a child"})
      )
    );
  }
};
Mihir
  • 3,812
  • 3
  • 25
  • 29