Home > Back-end >  TypeError: Cannot read properties of null (reading 'classList')
TypeError: Cannot read properties of null (reading 'classList')

Time:12-07

enter image description hereI am working in a nextjs application. I was just trying to make a dropdown.

This is my full code:

import React from 'react'
import Link from 'next/link'
import styles from './header.module.css'

const Header = () => {
    /* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
    const myFunction =()=>{
        document.getElementById(styles.myDropdown).classList.toggle("show");
    }

    // Close the dropdown menu if the user clicks outside of it
    if (typeof window !== "undefined") {
        window.onclick = function (event) {
            if (!event.target.matches('.dropbtn')) {
                var dropdowns = document.getElementsByClassName("dropdown-content");
                var i;
                for (i = 0; i < dropdowns.length; i  ) {
                    var openDropdown = dropdowns[i];
                    if (openDropdown.classList.contains('show')) {
                        openDropdown.classList.remove('show');
                    }
                }
            }
        }
      }

    return (
        <div className={styles.header}>
            <div className={styles.logoLink}>
                <img src="images/itacs.png" alt="" className={styles.logo} />
            </div>
            <div className={styles.services}>
                <ul>
                    <li><Link href="/page">Docs</Link></li>
                    <li><Link href="/page">Learn</Link></li>
                    <li><Link href="/page">Projects</Link></li>
                    <li><Link href="/page">Blog</Link></li>
                    <div className={styles.dropdown}>
                        <button onClick={myFunction} className={styles.dropbtn}>Dropdown</button>
                        <div id={styles.myDropdown} className={styles.dropdownContent}>
                            <a href="/">Link 1</a>
                            <a href="/">Link 2</a>
                            <a href="/">Link 3</a>
                        </div>
                    </div>
                </ul>
            </div>
            <form action="" className={styles.headerForm}>
                <a href="/" className={styles.logIn}>Log In</a>
                <a href="/" className={styles.getStarted}>Get Started</a>
            </form>
        </div>
    )
}

export default Header

Here I have just added the classlist in the id of div! I am trying to show the below div when the button is clicked as a dropdown menu. I am not able to figure this out!

For anyone who is wondering what is there present in css file :

/* dropdown */
/* Dropdown Button */
.dropbtn {
    background-color: #3498DB;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
  }
  
  /* Dropdown button on hover & focus */
  .dropbtn:hover, .dropbtn:focus {
    background-color: #2980B9;
  }
  
  /* The container <div> - needed to position the dropdown content */
  .dropdown {
    position: relative;
    display: inline-block;
  }
  
  /* Dropdown Content (Hidden by Default) */
  .dropdownContent {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
  }
  
  /* Links inside the dropdown */
  .dropdownContent a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
  }
  
  /* Change color of dropdown links on hover */
  .dropdownContent a:hover {background-color: #ddd}
  
  /* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
  .show {display:block;}

Any Help would be appreciated!

CodePudding user response:

It should be <div className="dropdown"> instead of <div > and <div id={styles.myDropdown} className={styles.dropdownContent}>

You would also avoid doing vanilla js inside a react/next app.

You would instead have a react state like this:

const [dropdownToggled, toggleDropdown] = useState(false);
  
const handleClick = () => {
  toggleDropdown(!dropdownToggled);
};

And have a condition on whether your jsx have a className hidden that sets display: none

something like this:

     <div
      className={`${styles.dropdownContent} 
      ${dropdownToggled ? styles.hidden : ""}`}
     >
       <a href="/">Link 1</a>
       <a href="/">Link 2</a>
       <a href="/">Link 3</a>
     </div>

Working CodeSandbox.

CodePudding user response:

If you use variables to set the id and className in the markup, you should probably use the same variables in your script, like

document.getElementById(`${styles.myDropdown}`).classList.toggle("show");

[Edit] or without the unnecessary redundant template string:

document.getElementById(styles.myDropdown).classList.toggle("show");

Assuming that styles.myDropdown is a string (not an object).

Otherwise your code does not ensure that the id and className will be the same.

  • Related