Next.js实现下拉菜单报Cannot read properties of null错误求助
错误原因
- 你将CSS Module的导出值作为id查询DOM,但你的
header.module.css中没有定义myDropdown类,styles.myDropdown实际为undefined,document.getElementById(undefined)返回null,调用classList时触发报错。 - CSS Module编译后类名会自动添加哈希后缀,你直接用纯字符串
.dropbtn、dropdown-content做DOM匹配,无法对应到实际渲染的类名,导致点击外部关闭逻辑完全失效。 - 直接在组件函数体内绑定
window.onclick,每次组件渲染都会覆盖之前的监听事件,且组件卸载时没有清理监听,会造成内存泄漏和逻辑冲突。 - React项目优先用状态控制UI,直接操作DOM不符合React的数据流逻辑,也容易出现渲染不同步的问题。
修复方案
完全采用React的状态和钩子实现下拉逻辑,无需手动操作DOM:
1. 组件代码修改
import React, { useState, useRef, useEffect } from 'react' import Link from 'next/link' import styles from './header.module.css' const Header = () => { // 控制下拉菜单显隐状态 const [isDropdownOpen, setIsDropdownOpen] = useState(false) // 绑定下拉容器DOM引用,用于判断点击区域是否在菜单外 const dropdownRef = useRef(null) // 切换下拉菜单显隐 const toggleDropdown = () => { setIsDropdownOpen(!isDropdownOpen) } // 监听点击外部关闭下拉 useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setIsDropdownOpen(false) } } document.addEventListener('mousedown', handleClickOutside) // 组件卸载时清理事件监听 return () => { document.removeEventListener('mousedown', handleClickOutside) } }, []) 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} ref={dropdownRef}> <button onClick={toggleDropdown} className={styles.dropbtn}>Dropdown</button> {/* 根据状态动态绑定show类 */} <div className={`${styles.dropdownContent} ${isDropdownOpen ? 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
2. CSS代码无需修改,原有样式可直接适配。
内容的提问来源于stack exchange,提问作者ITACS
相关产品推荐
相关产品推荐

