React使用useRef实现粘性头部时classlist读取null错误求助
问题解决:Cannot read properties of null (reading 'classList')
这个错误的核心原因是:当stickyHeaderFunc执行时,headerRef.current还没关联到实际的DOM元素(或者组件已被卸载),此时直接访问它的classList就会触发空值报错。
修复步骤:
- 给ref的DOM操作加空值判断
在操作classList之前,先确认headerRef.current不是null,避免直接访问空值的属性。 - 修正React属性小问题
React中DOM元素的类名属性是className,不是原生HTML的class,代码里的<i class="ri-menu-line"></i>需要修正,避免潜在问题。
修改后的完整代码:
import React, { useEffect, useRef } from "react"; import { Container, Row, Button } from "reactstrap"; import logo from "../../assets/images/logo.png"; import { Link, NavLink } from "react-router-dom"; import "./header.css"; const nav_links = [ { path: "/home", display: "Home", }, { path: "/about", display: "About", }, { path: "/tours", display: "Tours", }, ]; const Header = () => { const headerRef = useRef(null); const stickyHeaderFunc = () => { // 先判断ref是否关联到DOM元素,避免空值访问 if (!headerRef.current) return; if ( document.body.scrollTop > 80 || document.documentElement.scrollTop > 80 ) { headerRef.current.classList.add("sticky__header"); } else { headerRef.current.classList.remove("sticky__header"); } }; useEffect(() => { window.addEventListener("scroll", stickyHeaderFunc); return () => { window.removeEventListener("scroll", stickyHeaderFunc); }; }, []); return ( <header className="header" ref={headerRef}> <Container> <Row> <div className="nav__wrapper d-flex align-items-center justify-content-between"> <div className="logo"> <img src={logo} alt="旅游网站logo" /> </div> <div className="navigation"> <ul className="menu d-flex align-items-center gap-5"> {nav_links.map((item, index) => ( <li className="nav__item" key={index}> <NavLink to={item.path} className={(navClass) => navClass.isActive ? "active__link" : "" } > {item.display} </NavLink> </li> ))} </ul> </div> <div className="nav__right d-flex align-items-center gap-4"> <div className="nav__btns d-flex align-items-center gap-4"> <button className="btn secondary__btn"> <Link to="/login">Login</Link> </button> <button className="btn primary__btn"> <Link to="/Register">Register</Link> </button> </div> <span className="mobile__menu"> {/* 修正class为className */} <i className="ri-menu-line"></i> </span> </div> </div> </Row> </Container> </header> ); }; export default Header;
额外优化建议(可选):
scroll事件会频繁触发,你可以给stickyHeaderFunc加节流处理,减少函数执行次数,提升页面性能。比如用setTimeout实现简单节流:
const stickyHeaderFunc = () => { if (!headerRef.current) return; // 节流:100ms内只执行一次 clearTimeout(headerRef.current.timer); headerRef.current.timer = setTimeout(() => { if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) { headerRef.current.classList.add("sticky__header"); } else { headerRef.current.classList.remove("sticky__header"); } }, 100); };
内容的提问来源于stack exchange,提问作者rajee
相关产品推荐
相关产品推荐

