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

React中滚动事件监听器报错:nav1为NULL

React中实现滚动切换导航栏类名的解决方案

你遇到的nav1 is NULL错误,根源是React的虚拟DOM渲染时序问题:直接在组件函数顶层执行document.querySelector('.navbar')时,导航栏的DOM元素还没被渲染到页面上,自然获取不到。普通HTML/JS是在DOM加载完成后执行代码,所以不会有这个问题。

下面是两种符合React规范的实现方式:

方式一:用状态控制类名(推荐)

这种方式遵循React的数据流,通过状态变量控制类名,无需直接操作DOM:

import { useState, useEffect } from 'react';

function App() {
  // 用状态记录是否滚动超过70px
  const [isScrolled, setIsScrolled] = useState(false);

  useEffect(() => {
    // 滚动监听函数
    const handleScroll = () => {
      setIsScrolled(window.scrollY > 70);
    };

    // 添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    {/* 根据状态动态添加类名 */}
    <nav className={`navbar ${isScrolled ? 'new_nav' : ''}`}>
      {/* 导航栏内容 */}
    </nav>
  );
}

export default App;

方式二:用useRef获取DOM元素(原生操作方式)

如果习惯原生DOM操作逻辑,可以用useRef获取元素,确保在DOM渲染完成后执行操作:

import { useRef, useEffect } from 'react';

function App() {
  // 创建ref关联导航栏元素
  const navRef = useRef(null);

  useEffect(() => {
    const nav1 = navRef.current;
    // 滚动监听函数
    const handleScroll = () => {
      if (window.scrollY > 70) {
        nav1.classList.add('new_nav');
      } else {
        nav1.classList.remove('new_nav');
      }
    };

    // 添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时移除监听
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    {/* 将ref绑定到导航栏元素 */}
    <nav ref={navRef} className="navbar">
      {/* 导航栏内容 */}
    </nav>
  );
}

export default App;

关键注意点

  • 必须把滚动监听的逻辑放在useEffect中,确保回调在组件挂载(DOM渲染完成)后执行,才能正确获取到DOM元素。
  • 组件卸载时要移除滚动监听,避免内存泄漏。

内容的提问来源于stack exchange,提问作者palani vel k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 18:18:21