0

I want to create a build of my javascript application using react which currently is just a single file defined as below. It does nothing but creates a div and keeps on changing the color of the hello-world text after it mounts.

import * as React from "react";
import * as ReactDOM from "react-dom";

class App extends React.Component {
    componentDidMount() {
        const colorBox = ["red","blue","green"];
        const element = document.getElementById("my-div");
        setInterval(() => {
            element.style.color = colorBox[parseInt(Math.floor(Math.random() * colorBox.length))];
        }, 3000);
    }

    render() {
        return (
            <div id={"my-div"}>
                Hello, World.
            </div>
        );
    }
}

ReactDOM.render(<App />,         
    document.body.appendChild(document.createElement("div")));

I am using parcel js as a bundler. I bundle my javascript as parcel build index.js and this creates a build of my javascript file inside dist folder. So far, so good. But the moment, I load this javascript using a script tag on my website as:

<script type="text/javascript" src="https://mycdn.com/bundle.index.js"></script>

It throws an error

    index.js:16 Uncaught TypeError: Cannot read property 'appendChild' of null
    at Object.parcelRequire.Focm.react (index.js:16)
    at f (index.js:1)
    at parcelRequire.YOwE (index.js:1)
    at index.js:1

Why it cannot access appendChild of document.body? I also checked that document.body is null. What is happening here? What is it that I am missing?

Suhail Gupta
  • 19,563
  • 57
  • 170
  • 298

2 Answers2

1

First of all I'm not sure this is a great idea to have code in the bundle that directly affects the page like this.

My guess as to why this is happening is it has to do with when the bundle is loaded in the page. Is it in head? If so document.body may not be available.

It is probably best if you are going to do something like this to use the events associated with the document being ready.

This can get complicated depending on your needs, but if you have access to jQuery, you can use .ready().

If not you can use various vanilla js options.

pixelearth
  • 11,254
  • 8
  • 49
  • 87
  • I have a widget that I created using vanilla js. Now I want to port this to ReactJS and thus this attempt. Is there a better way to create an embeddable widget using React? – Suhail Gupta Oct 24 '20 at 06:17
0

I guess your problem is related to the bundle or you ask for an element before it is available because it is working fine here: https://jsfiddle.net/rL6dnhps

If you load it from the head, try to put at the end of the body in order to wait for the body to be ready or wrap it inside an IIFE like below:

(function() {
    // the DOM will be available here
    ReactDOM.render(<App />,         
    document.body.appendChild(document.createElement("div")));
})();
Amadou Beye
  • 1,962
  • 1
  • 11
  • 24