Cannot read properties of null (reading addEventListener)

avatar
Borislav Hadzhiev

Last updated: Mar 3, 2024
3 min

banner

# Cannot read properties of null (reading 'addEventListener')

There are 2 main reasons the "Cannot read properties of null (reading 'addEventListener')" error occurs:

  • Accessing the addEventListener() method on an element that doesn't exist.
  • Inserting the JS script tag above the HTML where the DOM elements are declared.

cannot read property addeventlistener of null

The main reason the error occurs is when you try to call the addEventListener() method on a DOM element that isn't found.

index.js
const btn = document.getElementById('does-not-exist'); console.log(btn); // ๐Ÿ‘‰๏ธ null // โ›”๏ธ Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') btn.addEventListener('click', () => { console.log('btn clicked'); });

We used an id that isn't present in the DOM, so the getElementById method returned null.

# Make sure the DOM element exists before calling addEventListener

The error also occurs when we call the addEventListener() method on a DOM element that doesn't exist.

To solve the error, use an if statement to check if the DOM element exists before calling the addEventListener() method.

index.js
const btn = document.getElementById('does-not-exist'); console.log(btn); // ๐Ÿ‘‰๏ธ null // โœ… Check if btn exists before addEventListener() if (btn) { btn.addEventListener('click', () => { console.log('btn clicked'); }); }
The code for this article is available on GitHub

Make sure to pass the correct identifier to the getElementById method and add an if statement to check if the DOM element exists.

You can also use the optional chaining (?.) operator, which short-circuits instead of throwing an error.

index.js
const btn = document.getElementById('does-not-exist'); console.log(btn); // ๐Ÿ‘‰๏ธ null // โœ… Using optional chaining (?.) btn?.addEventListener('click', () => { console.log('btn clicked'); });
If the value of the btn variable is null or undefined, the operator returns undefined, otherwise, it calls the method.

# Place the JS script tag at the bottom of the body tag

Make sure to insert the JS script tag at the bottom of the body tag.

The JS script tag should be placed after the HTML elements have been declared.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <!-- โŒ BAD - Script is run before the button is created โŒ --> <script src="index.js"></script> <button id="btn">Submit</button> </body> </html>
The code for this article is available on GitHub

The JS script tag in the example is placed before the button element is declared, so the button element will not be available in the index.js file.

index.js
const btn = document.getElementById('btn'); console.log(btn); // ๐Ÿ‘‰๏ธ null // โ›”๏ธ cannot read properties of null (reading 'addEventListener') btn.addEventListener('click', () => { console.log('btn clicked'); });

You have to move the JS script tag to the bottom of the body, after the HTML elements have been declared.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <button id="btn">Submit</button> <!-- โœ… GOOD - HTML is already declared โœ… --> <script src="index.js"></script> </body> </html>

place js script tag at bottom of body tag

The code for this article is available on GitHub

Now the index.js file has access to the DOM elements because they have already been declared by the time the script is run.

index.js
const btn = document.getElementById('btn'); console.log(btn); // โœ… Works as expected btn.addEventListener('click', () => { console.log('btn clicked'); });

calling addeventlistener method successfully

The code for this article is available on GitHub

HTML code is parsed from top to bottom, so the script tag has to be placed at the bottom of the body tag, after all of the DOM elements it needs to access.

The button element is found and the getElementById method returns the actual element and not null, so we can call the element's addEventListener method and attach an event listener.

# Using the DOMContentLoaded event to solve the error

You can also use the DOMContentLoaded event to solve the error.

The event runs when the HTML document has been completely parsed and all scripts have been downloaded and executed.

When using this approach, the script doesn't necessarily have to be at the bottom of the body tag.

index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <!-- ๐Ÿ‘‡๏ธ moved script in head tag --> <script src="index.js"></script> </head> <body> <button id="btn">Submit</button> </body> </html>
The code for this article is available on GitHub

And here is the related JavaScript code.

index.js
document.addEventListener('DOMContentLoaded', () => { const btn = document.getElementById('btn'); console.log(btn); // โœ… Works as expected btn.addEventListener('click', () => { console.log('btn clicked'); }); });
The code for this article is available on GitHub

By the time the DOMContentLoaded event runs, the HTML document has been completely parsed, so the DOM elements are available in the index.js file.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev