ReferenceError: document is not defined (in plain JavaScript)

Javascript

Javascript Problem Overview


I get the a "ReferenceError: document is not defined" while trying to

var body = document.getElementsByTagName("body")[0];

I have seen this before in others code and didn't cause any trouble. Why is it now? The companied HTML page is just a div inside the body.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/quiz.css" />
    <script type="text/javascript" src="js/quiz.js"></script>
</head>
<body>

    <div id="divid">Next</div>

</body>
</html>

the code is the following:

(function(){
        var body = document.getElementsByTagName("body")[0];
    
        function Question(question, choices, correctAns) {
            this.question = question;
            this.choices = choices;
            this.correctAns = correctAns;
        }
    
        Question.prototype.checkAns = function(givenAns){
            if (this.correctAns === givenAns) {
                console.log("OK");
            }
        };
    
        function Quiz() {
            this.questions = [];
        }
    
        Quiz.prototype.showAllQuestions = function(){
            this.questions.forEach(function(questions){
                console.log(questions.question);
            });
        };
    
        Quiz.prototype.showQuiz = function(){
            this.questions.forEach(function(questions){
    
                for (var i=0; i < questions.choices.length; i+=1) {
                    body.innerHTML(
                            "<input type=\"radio\" name=\"sex\" value=\"male\">" 
                            + questions.choices[i] + "<br>");
                }
    
            });
        };
    
        var q1 = new Question("What is red?", ["Color","Animal","Building"],1);
        var q2 = new Question("Most popular music?", ["Latin","Pop","Rock"],2);
        var quiz = new Quiz();
    
        quiz.questions.push(q1);
        quiz.questions.push(q2);
        quiz.showAllQuestions();
    
    
        })();

Try the whole code in this link HERE

Javascript Solutions


Solution 1 - Javascript

This happened with me because I was using Next JS which has server side rendering. When you are using server side rendering there is no browser. Hence, there will not be any variable window or document. Hence this error shows up.

Work around :

If you are using Next JS you can use the dynamic rendering to prevent server side rendering for the component.

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(() => import('../components/List'), {
  ssr: false
})

export default () => <DynamicComponentWithNoSSR />

If you are using any other server side rendering library. Then add the code that you want to run at the client side in componentDidMount. If you are using React Hooks then use useEffects in the place of componentsDidMount.

import React, {useState, useEffects} from 'react';

const DynamicComponentWithNoSSR = <>Some JSX</>

export default function App(){

[a,setA] = useState();
useEffect(() => {
    setA(<DynamicComponentWithNoSSR/>)
  });


return (<>{a}<>)
}

References :

  1. https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
  2. https://reactjs.org/docs/hooks-effect.html

Solution 2 - Javascript

It depends on when the self executing anonymous function is running. It is possible that it is running before window.document is defined.

In that case, try adding a listener

window.addEventListener('load', yourFunction, false);
// ..... or 
window.addEventListener('DOMContentLoaded', yourFunction, false);

yourFunction () {
  // some ocde

}

Update: (after the update of the question and inclusion of the code)

Read the following about the issues in referencing DOM elements from a JavaScript inserted and run in head element:

Solution 3 - Javascript

Try adding the script element just before the /body tag like that

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/quiz.css" />
</head>
<body>

    <div id="divid">Next</div>
    <script type="text/javascript" src="js/quiz.js"></script>
</body>
</html>

Solution 4 - Javascript

You may deactivate ssr for the whole component (check Trect's answer), but it's overkill since you only need to skip one line in ssr.

You should only check if document is defined (determining if the function is called server-side -no document- or client-side -document defined-):

if (typeof document === 'undefined') {
    // during server evaluation
} else {
    // during client's browser evaluation
}

In your case, you don't need to do anything server-side, you may do something like:

var body = null;

if (typeof document !== 'undefined') {
    // will run in client's browser only
    body = document.getElementsByTagName("body")[0];
}

Solution 5 - Javascript

Adding "defer" attribute to <script> tag can also fix it.

<script defer src="yourScript.js"></script>   

In this case you can keep <script> inside of <head>.

Solution 6 - Javascript

This issue happened when you call the eliment which didn't created yet You called the body and it's component in <head > Call the file in the end of< body > Just before </body> will solve it.

Solution 7 - Javascript

If you want to access the HTML DOM Document Object directly in Typescript, this implies that you will use the browser as the environment and have the Type Script tooling generate the code behind, while you use a code editor like VsCode to debug through your typescript.

const document: Document = document as Document;

or if you want to use it into a class just do:

class ExampleClass {
   private document: Document;
   private btn: HTMLElement;

   constructor() {
       this.document = document as Document;
   }

   public exampleOfGettingAButton(): void {
       this.btn = this.document.getElementById("my-btn");
   }
}

Solution 8 - Javascript

Problem: I got this error while using tailwind components from [tailwind-elements]. (https://tailwind-elements.com/)

Explanation: The error is caused because NextJs renders the page in the server only and in the server document (document is used inside tailwind-elements)is not available.

Solution: Use a dynamic route from NextJS.

import dynamic from "next/dynamic";

const {} = dynamic(import("tw-elements"), { ssr: false });

Solution 9 - Javascript

try: window.document......

var body = window.document.getElementsByTagName("body")[0];

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlimitcrackerView Question on Stackoverflow
Solution 1 - JavascriptTrectView Answer on Stackoverflow
Solution 2 - JavascripterosmanView Answer on Stackoverflow
Solution 3 - JavascriptAbdelwahab MahmoudView Answer on Stackoverflow
Solution 4 - JavascriptVincent JView Answer on Stackoverflow
Solution 5 - JavascriptAlexander WakkaView Answer on Stackoverflow
Solution 6 - JavascriptAly AbdelaalView Answer on Stackoverflow
Solution 7 - JavascriptDavid PView Answer on Stackoverflow
Solution 8 - JavascriptChetan B BView Answer on Stackoverflow
Solution 9 - JavascriptNgannvView Answer on Stackoverflow