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

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

我正在 nextjs 应用程序中工作。我只是想做一个下拉菜单。

这是我的完整代码:

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

这里我刚刚在div的id中添加了classlist! 当单击按钮作为下拉菜单时,我试图显示下面的 div。 我想不通!

任何想知道 css 文件中存在什么的人:

/* 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;}

如有任何帮助,我们将不胜感激!

如果您使用变量在标记中设置 id 和 className,您应该在脚本中使用相同的变量,例如

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

[编辑]或去掉不必要的冗余模板字符串:

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

假设styles.myDropdown是一个字符串(不是对象)。

否则您的代码无法确保 idclassName 相同。

应该是<div className="dropdown">而不是<div class="dropdown"><div id={styles.myDropdown} className={styles.dropdownContent}>

您还应避免在 react/next 应用程序中使用 vanilla js。

你会有这样的反应状态:

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

并且有一个条件,你的 jsx 是否有一个 className hidden 设置 display: none

像这样:

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

要在用户点击外部时关闭下拉菜单,您需要这样的 div:

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

样式如下:

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

现在,由于此 div 占据了整个屏幕,并且在用户单击页面上的任意位置时处于绝对位置,因此 onClick 将触发并切换下拉菜单。

Working CodeSandbox.

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

是的,终于配置好了。感谢whygee and Ingo Steinkie