Last updated: Mar 3, 2024
Reading timeยท3 min
There are 2 main reasons the "Cannot read properties of null (reading 'addEventListener')" error occurs:
addEventListener()
method on an element that doesn't exist.The main reason the error occurs is when you try to call the
addEventListener()
method on a DOM element that isn't found.
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
.
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.
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'); }); }
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.
const btn = document.getElementById('does-not-exist'); console.log(btn); // ๐๏ธ null // โ Using optional chaining (?.) btn?.addEventListener('click', () => { console.log('btn clicked'); });
btn
variable is null
or undefined
, the operator returns undefined
, otherwise, it calls the method.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.
<!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 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.
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.
<!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>
Now the index.js
file has access to the DOM elements because they have already
been declared by the time the script is run.
const btn = document.getElementById('btn'); console.log(btn); // โ Works as expected btn.addEventListener('click', () => { console.log('btn clicked'); });
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.
DOMContentLoaded
event to solve the errorYou can also use the DOMContentLoaded
event to solve the error.
When using this approach, the script doesn't necessarily have to be at the
bottom of the body
tag.
<!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>
And here is the related JavaScript code.
document.addEventListener('DOMContentLoaded', () => { const btn = document.getElementById('btn'); console.log(btn); // โ Works as expected btn.addEventListener('click', () => { console.log('btn clicked'); }); });
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.