React响应式导航栏报错:Cannot read properties of null (reading 'classList')
修复React响应式导航栏的ClassList空指针错误
问题根源
你现在的代码在组件外部直接执行document.querySelector(".menu-icon")和document.querySelector(".ul"),这时候React还没完成组件渲染,对应的DOM元素还未挂载到页面,所以这两个查询返回的都是null。点击菜单图标触发menue函数时,访问null的classList属性就会抛出Cannot read properties of null (reading 'classList')错误。
另外,直接操作DOM不符合React状态驱动UI的设计模式,应该通过React状态控制元素样式类。
修复方案
- 使用
useState钩子管理导航栏展开状态 - 将事件处理函数移到组件内部,确保能访问组件状态
- 通过状态动态切换元素className,替代原生DOM操作
- 修正a标签的无效href属性
完整修正代码
JSX代码(Header.jsx)
import "./header.css"; import React, { useState } from "react"; function Header() { // 用状态管理导航栏展开状态 const [isMenuOpen, setIsMenuOpen] = useState(false); const toggleMenu = () => { setIsMenuOpen(prev => !prev); }; return ( <nav> <div className="navbar"> <div className="logo"> {/* 修正图片路径,public下的资源直接写/images/logo.svg即可 */} <img src="/images/logo.svg" alt="Logo" /> </div> {/* 根据状态动态添加open类 */} <ul className={`ul ${isMenuOpen ? 'open' : ''}`}> <li> <a href="/">Home</a> </li> <li> <a href="/about">About</a> </li> <li> <a href="/classes">Classes</a> </li> <li> <a href="/trainers">Trainers</a> </li> <li> <a href="/news">News</a> </li> <li> <a href="/contact">Contact</a> </li> </ul> </div> <div className="btn"> <button>Book Class</button> </div> <div className="menu"> {/* 根据状态动态切换图标类 */} <i className={`ri-menu-line menu-icon ${isMenuOpen ? 'bx-x' : ''}`} onClick={toggleMenu} ></i> </div> </nav> ); } export default Header;
CSS代码(header.css)
*{ box-sizing: border-box; margin: 0; padding: 0; font-family: sans-serif; } nav{ position: fixed; top: 0; right: 0; z-index: 100; display: flex; justify-content: space-around; align-items: center; padding: 28px 12%; width: 100%; } .navbar{ display: flex; justify-content: space-between; align-items: center; width: 100%; } ul{ display: flex; align-items: center; justify-content: space-evenly; gap: 10px; } nav ul li{ list-style: none; } nav ul li a{ text-decoration: none; font-size: 0.7rem; color: black; margin-top: 0; margin-bottom: 0; position: relative; padding: 0px 5px; } nav ul li a::after{ content: ""; background-color: #a1f65e; height: 2px; position: absolute; width: 100%; left: 0; bottom: -5px; border-radius: 100px; transition: 0.3s ease-in-out; transform: scale(0, 1); } nav ul li a:hover::after{ transform: scale(1,1); } .logo img{ width: 13vw; } .btn button{ padding: 0.8rem; width: 10vw; border: none; background-color: #e8e8e8; margin-left: 2rem; font-size: 0.8rem; font-family: sans-serif; font-weight: 600; transition: 0.1s ease-in-out; font-family: sans-serif; } .btn button:hover{ background: #dcdcdc; cursor: pointer; } .btn button:active{ transform: scale(0.7); } nav .menu i{ display: none; } @media (max-width: 1100px){ nav{ justify-content: space-between; transition: 0.2s; padding: 28px 30px; } .btn button{ font-size: 0.7rem; width: 20vw; } } @media (max-width: 800px){ .btn button{ font-size: 0.5rem; } nav .menu i{ display: block; margin-left: 10px; font-size: 1.2rem; font-weight: 100; transition: 0.1s ease-in-out; } nav .menu i:hover{ cursor: pointer; } nav .menu i:active{ transform: scale(0.7); cursor: pointer; } nav ul{ position: absolute; top: 90%; right: -100%; width: 35vw; height: 11rem; background-color: #a1f65e; display: flex; justify-content: center; align-items: flex-start; flex-direction: column; z-index: 101; padding: 10px; border-radius: 10px; transition: 0.2s ease-in-out; color: white; } .logo img{ width: 30vw; } nav ul li a{ display: block; margin: 0.1rem 0; padding: 0px 20px; color: rgb(255, 255, 255); transition: 0.5s all ease; } nav ul li a:hover{ color: rgb(0, 0, 0); transform: translateY(5px); } nav ul.open{ right: 2%; } }
关键改动说明
- 用
useState创建isMenuOpen状态,控制菜单展开/收起 - 点击菜单图标时调用
toggleMenu函数,切换状态值 - 通过模板字符串动态为ul和图标元素添加对应类名,替代直接操作DOM的classList
- 修正图片路径(public目录下的资源直接以/开头访问)
- 修正a标签的href属性,改为有效的路由路径
内容的提问来源于stack exchange,提问作者Binary Bro
相关产品推荐
相关产品推荐

