Simple photo gallery - Uncaught TypeError: Cannot read property 'insertBefore' of null

Hi, would really appreciate some help. I am currently undertaking an online Javascript course, and in a previous session we were creating a simple photo gallery, but my computer crashed so I missed the explanation. Anyway, our tutor provided his code after and I since attempted it on my own. When this wasn’t working, I referred back to the code he provided and copied it exactly. However, it doesn’t work and I get this error in the console every time: “Uncaught TypeError: Cannot read property ‘insertBefore’ of null”.

I am very much at the beginning of my JS journey, and my understanding is limited. I’m also working through the FreeCodeCamp JS course at the same time. I just don’t understand why I’m getting this error, especially if I’m using the same code as my tutor, and as far as I understand his is working. I’d really appreciate some help on this as I want to resolve this weekend and I have already spent hours on Google trying. I feel stupid!

Thanks in advance.

HTML

    <p><img id="fullSized" src="" alt="Full sized placeholder"></p>
   
    <p id="thumbPoint"></p>

JS

      //1 array of photos for link and source 
        let photos = [
            {
                'href': 'imgs/p0.jpg',
                'src': 'imgs/p0.jpg',
                
            },
            {
                'href': 'imgs/p1.jpg',
                'src': 'imgs/p1.jpg', 
            },
            {
                'href': 'imgs/p2.jpg',
                'src': 'imgs/p2.jpg',
            },
            {
                'href': 'imgs/p3.jpg',
                'src': 'imgs/p3.jpg',
            },
             
        ],
            
        //2 global variables
            
            insertPoint = document.getElementById('thumbPoint'),
            
            thumbnail,
            
            a_tag;
        
        //3 loop
        
        for (i = 0; i < photos.length; i++){
                a_tag = document.createElement('a');
                a_tag.href = photos[i].href;
                
                thumbnail = document.createElement('img');
                thumbnail.src = photos[i].src;
                thumbnail.width = '100';
                thumbnail.height = '100';
                
                a_tag.appendChild(thumbnail);
                
                document.body.insertBefore(a_tag, insertPoint);
                
                a_tag.addEventListener('click', showImage);
                
                     
            }
        
        //4 
        
        document.getElementById('fullSized').src = photos[0].href;
        
        //5 
        
        function showImage (o){
             console.log ('here');
            o.preventDefault();
            document.getElementById('fullSized').src = this.href;
            
        }

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (’).

1 Like

Thank you for letting me know and editing this - will be sure to do this going forward.

You haven’t declared any variables. In JavaScript, you declare a variable with a keyword let or const like this:

let insertPoint = document.getElementById('thumbPoint');

let thumbnail;

for (let i=0; i < photos.length; i++) {

to list just a few.

I’m not sure if that’ll already fix all issues, but that’s something to start with.

Thanks for your feedback. My tutor said that you don’t always need to declare global variables like this, and his code has them declared in the same way as the code I posted. But I was under the impression that you needed ‘let’ or const’ in front, as you mentioned…

Anyhow, I tried declaring the variables with the let keyword, and then I get an error saying “Uncaught SyntaxError: let is disallowed as a lexically bound name” instead. Will keep trying to figure this out.

Thanks again

Technically, you don’t need to declare your variables with a keyword, that’s true. But it’s horrible practice. If someone teaches you JavaScript like this, I’d consider finding another tutor…

That’s probably because you’ve declared them like this:

           let  insertPoint = document.getElementById('thumbPoint'),
          let  thumbnail,
          let  a_tag;

That won’t work, you’ll need to replace those commas at the end of each line with semicolons.

Otherwise, only use let for the first declaration:

           let insertPoint = document.getElementById('thumbPoint'),
           thumbnail,
           a_tag;

Hi, I had changed all of the commas to semicolons before reloading and got that error message. After reading your message, I Googled something in relation and read that I needed to, before changing anything. Strange huh.

Thanks for the advice on what my tutor had taught… Slightly concerning but good to know!

Do you still get the error “Uncaught TypeError: Cannot read property ‘insertBefore’ of null” or does it work now?

No, that error doesn’t appear, so thank you for resolving that, but the code still doesn’t work and the error message “Uncaught SyntaxError: let is disallowed as a lexically bound name” comes up instead.

Do I need to declare the let keyword in front of all uses of a_tag and thumbnail variables within the function too? Updated code below. Thanks very much for all your help!

      //2 global variables
            
            let insertPoint = document.getElementById('thumbPoint');
            
            let thumbnail;
            
            let a_tag;
        
        //3 loop
        
        for (let i = 0; i < photos.length; i++){
                a_tag = document.createElement('a');
                a_tag.href = photos[i].href;
                
                thumbnail = document.createElement('img');
                thumbnail.src = photos[i].src;
                thumbnail.width = '100';
                thumbnail.height = '100';
                
                a_tag.appendChild(thumbnail);
                
                document.body.insertBefore(a_tag, insertPoint);
                
                a_tag.addEventListener('click', showImage);
                
                     
            }

This error is still there because there’s still a comma after the declaration of the photos variable, that should be a semicolon too.

After you’ve declared a variable with let, JavaScript knows it’s a variable. In fact, you’d get an error if you want to redeclare it with let again.

In your example, the global scope is aware of the variables insertPoint, thumbnail and a_tag, and the function can look outside itself and knows what those variables are, so no need to re-declare them inside the function.

A result of copying my tutor’s code, have fixed now, but the "Uncaught TypeError: Cannot read property ‘insertBefore’ of null is back.

This is a great explanation. Thanks.

You’re trying to use the .insertBefore method on document.body, which should definitely not be null. Unless your script runs before the DOM is loaded, so I’d suggest the following, wrap your whole code inside an event listener like this:

document.addEventListener('DOMContentLoaded', () => {

    // your whole code goes here within the curly braces

}