Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Cannot read properties of null (reading 'classList')

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!

like image 935
ITACS Avatar asked Jul 17 '26 13:07

ITACS


2 Answers

It should be <div className="dropdown"> instead of <div class="dropdown"> 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>

To make the dropdown close when the user clicks outside, you would have a div like this:

<div
  className={styles.backdrop}
  onClick={() => toggleDropdown(true)}
></div>

that is styled like this:

.backdrop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  z-index: -1;
}

Now since this div takes the whole screen and is positioned absolute when the user clicks anywhere on the page the onClick will fire and toggle the dropdown.

Working CodeSandbox.

like image 122
whygee Avatar answered Jul 19 '26 04:07

whygee


import React, { useState } from 'react'
import Link from 'next/link'
import styles from './header.module.css'

const Header = () => {
    const [dropdownToggled, toggleDropdown] = useState(false);

    const handleClick = () => {
        toggleDropdown(!dropdownToggled);
        console.log("boy");
    };

    // 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(styles.dropdownContent);
                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={handleClick} id="dropbtn" className={styles.dropbtn}>Dropdown</button>
                        <div
                            className={`${styles.dropdownContent} ${dropdownToggled ? styles.show : ""}`}
                        >
                            <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

Yea finally configured it out. Thanks to whygee and Ingo Steinkie

like image 29
ITACS Avatar answered Jul 19 '26 04:07

ITACS