You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React使用useRef实现粘性头部时classlist读取null错误求助

问题解决:Cannot read properties of null (reading 'classList')

这个错误的核心原因是:当stickyHeaderFunc执行时,headerRef.current还没关联到实际的DOM元素(或者组件已被卸载),此时直接访问它的classList就会触发空值报错。

修复步骤:

  1. 给ref的DOM操作加空值判断
    在操作classList之前,先确认headerRef.current不是null,避免直接访问空值的属性。
  2. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:28:19