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

React/Next.js中改写JS事件监听与类名切换问题求助

问题解决:React/Next.js中替换原生DOM操作实现类名切换

问题根源

你的代码直接使用原生DOM API操作元素类名,不符合React的状态驱动理念,同时在Next.js的SSR(服务端渲染)环境中,document对象在服务端不存在,会触发警告,进而导致webpack缓存序列化失败(即你看到的错误)。另外,未清理的事件监听器还会引发内存泄漏,导致页面刷新后功能失效。

重构方案:用React状态+内置API替代原生DOM操作

下面是修改后的完整Header组件,完全遵循React的状态管理逻辑:

import React, { useState, useEffect } from 'react'
import { FaFacebookSquare, FaGithubSquare, FaInstagramSquare, FaYoutubeSquare } from 'react-icons/fa'
import { ImMenu } from 'react-icons/im'
import { BiSearchAlt } from 'react-icons/bi'

const Header = () => {
  // 菜单展开状态
  const [isMenuOpen, setIsMenuOpen] = useState(false)
  // Navbar激活状态
  const [isNavbarActive, setIsNavbarActive] = useState(false)
  const offset = 50

  // 滚动监听逻辑,添加清理函数
  useEffect(() => {
    const handleScroll = () => {
      setIsNavbarActive(window.pageYOffset > offset)
    }

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

  return (
    <div className='header1'>
      <video id='headerVideo' loop autoplay muted>
        <source src="/vidfy-african-cheerful-young-stylish-man-and-w_1920x1080.mp4" type="video/mp4" />
        Your browser does not support the video tag.
      </video>
    
      <div>
        {/* 动态绑定navbar的类名 */}
        <nav id='navbar' className={isNavbarActive ? 'navbar-active' : ''}>
          {/* 动态绑定menu的类名 */}
          <div className={`menu ${isMenuOpen ? 'menu-open' : ''}`}>
            <div>
              <a href="#" className='brand'>Menu</a>
              <ul>
                <li><a href="#">Blog</a></li>
                <li><a href="#">What's New</a></li>
                <li><a href="#">Categories</a></li>
              </ul>

              <ul>
                <li><a href="#">Projects</a></li>
                <li><a href="#">News</a></li>
                <li><a href="#">Store</a></li>
                <li><a href="#">About</a></li>
                <li><a href="#">Contact</a></li>
              </ul>

              <ul className='social-media'>
                <li><a href="#"><FaFacebookSquare /></a></li>
                <li><a href="#"><FaInstagramSquare /></a></li>
                <li><a href="#"><FaGithubSquare /></a></li>
                <li><a href="#"><FaYoutubeSquare /></a></li>
              </ul>

              <form action="">
                <div className="input-wrap">
                  <input type="search" placeholder='Search...' />
                  <button type='submit'><BiSearchAlt /></button>
                </div>
              </form>
            </div>
          </div>

          <div className="container">
            <a href="#" className="logo"><img src="/logo.png" alt="logo" /></a>
            <div className="container-inner">
              <ul>
                <li><a href="#">Home</a></li>
                <li><a href="#">Home</a></li>
                <li><a href="#">Home</a></li>
              </ul>

              <form action="">
                <div className="input-wrap">
                  <input type="search" placeholder='Search...' className='text-is-white' />
                  <button type='submit'><BiSearchAlt /></button>
                </div>
              </form>
            </div>
            {/* 直接绑定点击事件,切换菜单状态 */}
            <ImMenu className='fa-bars' id='menu-btn' onClick={() => setIsMenuOpen(!isMenuOpen)} />
          </div>
        </nav>
      </div>

      <div className="headText">
        <p>Grow your business and ideas with KimmoTech</p>
      </div>
    </div>
  )
}

export default Header

关键修改点说明

  • 菜单切换:用useState维护isMenuOpen状态,点击菜单按钮时直接切换状态,通过模板字符串动态给.menu添加/移除menu-open类。
  • 滚动监听:用useState维护isNavbarActive状态,滚动时更新状态,动态给#navbar添加/移除navbar-active类;同时添加了监听器清理函数,避免组件卸载后内存泄漏。
  • 移除原生DOM操作:完全抛弃getElementById、querySelector和addEventListener,改用React内置的事件绑定和状态驱动DOM更新,适配Next.js的SSR环境。

为什么原代码会触发webpack错误

Next.js在服务端渲染时,会尝试序列化缓存内容,但原生DOM操作会引发警告(服务端不存在document),而这些警告无法被webpack缓存序列化器处理,最终导致你看到的缓存跳过错误。重构后完全避免了服务端的DOM操作,警告消失,缓存问题也会解决。

内容的提问来源于stack exchange,提问作者Chidimma Nworah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:39:17