-1

I have an HTML page, which making get request to the react page hosted in other domain. Once, i get page response, i copy JS from head section of requested page to head section of my page and same for script available in body section.

Requested page is an react page which contain react and react-dom in head section and other JS chunk in body section, which will get copy to same section on my page.

I thought, any script copied to head section of page immediately block page execution and once all script in head get executed then only scrip in body will execute.

I'm getting intermittent client side error of "ReactDOM is not defined". It seems script copied to body is getting executed before script in head is fully executed.

ReactJS and ReactDOM JS is in head section of page and chunk which throwing error is in body.

external "ReactDOM":1 Uncaught ReferenceError: ReactDOM is not defined
    at Object.faye (external "ReactDOM":1)
    at f (bootstrap:83)
    at Module.7n5H (tes1.ts:18)
    at f (bootstrap:83)
    at Object.0 (test2.ts:114)
    at f (bootstrap:83)
    at t (bootstrap:45)
    at Array.r [as push] (bootstrap:32)
    at 0.9efbe0e7cdf36824.chunk.js?_=1555361723703:1 faye @ external "ReactDOM":1 f @ bootstrap:83 7n5H @ tes1.ts:18 f @ bootstrap:83 0 @ test2.ts:114 f @ bootstrap:83 t @ bootstrap:45 r @ bootstrap:32 (anonymous) @ 0.9efbe0e7cdf36824.chunk.js?_=1555361723703:1
user1760384
  • 107
  • 2
  • 9

1 Answers1

0

This is quite simple and it doesn't really have to do with code being in the head nor body, the call to get the react files is a bit slow, so it doesn't make in time for your code in body to use it therefore it's undefined

Ex. The issue

// this is the we will put in the body 
// log the react object to the console simple
let body = "console.log(React)"

// im using a button to make it easier to understand
document.querySelector('input').onclick = () => {


  // here we are assing a scrupt tag to the head
  // with the link to the react lib
  let headscript = document.createElement('script');
  headscript.src = "https://unpkg.com/react@15/dist/react.js"
  document.querySelector('head').appendChild(headscript);


  // and here we are logging the React object
  // from the body
  let bodyscript = document.createElement('script');
  bodyscript.innerHTML = body;
  document.querySelector('body').appendChild(bodyscript);
};
Click once and wait a bit then click again
<br>
<input type="button" value="click me">

As you can see it's just the good old problem with async operations, solution is to use promises.

Demo

let body = "console.log(React)"
document.querySelector('input').onclick = () => {
  // request to get the code
  fetch("https://unpkg.com/react@15/dist/react.js")
    // returning it as plain text because that what it is
    .then(response => response.text())
    .then(data => {
      // same as before
      let headscript = document.createElement('script');
      headscript.innerHTML = data;
      document.querySelector('head').appendChild(headscript);

      // and because all code inside the reac lib is not async
      // this is safe to call right after
      let bodyscript = document.createElement('script');
      bodyscript.innerHTML = body;
      document.querySelector('body').appendChild(bodyscript);
    })
};
<input type="button" value="click me">
Rainbow
  • 6,772
  • 3
  • 11
  • 28