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

迁移React项目后Jquery滚动函数报错:Cannot read properties of undefined (reading 'top')

解决React迁移中滚动功能报错:Cannot read properties of undefined (reading 'top')

问题根源

你遇到的报错是因为jQuery执行时目标section元素还未被React渲染到DOM中,导致$('#section_' + value)返回空集合,调用.offset()得到undefined,进而访问.top时触发报错。另外,在React项目中混合使用jQuery操作DOM,会和React的虚拟DOM管理机制冲突,容易出现渲染不同步、事件失效等问题。

解决方案:改用React原生方式实现滚动功能

完全移除原有的jQuery脚本,用React的hooks(useRef、useState、useEffect)来实现滚动监听和锚点滚动功能,以下是完整实现:

1. 完整TSX组件代码

import { useState, useEffect, useRef } from 'react';

const App = () => {
  // 保存所有section的ref
  const sectionRefs = {
    section_1: useRef<HTMLElement>(null),
    section_2: useRef<HTMLElement>(null),
    section_3: useRef<HTMLElement>(null),
  };
  // 管理当前激活的导航索引
  const [activeIndex, setActiveIndex] = useState(0);
  // 导航项配置
  const navItems = [
    { label: 'Home', target: 'section_1' },
    { label: 'About', target: 'section_2' },
    { label: 'Ecosystem', target: 'section_3' },
  ];

  // 滚动监听逻辑
  useEffect(() => {
    const handleScroll = () => {
      const scrollTop = window.scrollY;
      // 遍历所有section,判断当前滚动位置对应的激活项
      Object.entries(sectionRefs).forEach(([key, ref], index) => {
        if (ref.current) {
          const offsetTop = ref.current.offsetTop - 83;
          // 当滚动位置超过section的偏移量时,设置为激活项
          if (scrollTop + 1 >= offsetTop) {
            setActiveIndex(index);
          }
        }
      });
    };

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

  // 点击导航滚动到对应section的逻辑
  const handleNavClick = (e: React.MouseEvent<HTMLAnchorElement>, targetKey: string) => {
    e.preventDefault();
    const targetRef = sectionRefs[targetKey as keyof typeof sectionRefs].current;
    if (targetRef) {
      // 计算滚动目标位置
      const targetScrollTop = targetRef.offsetTop - 83;
      window.scrollTo({
        top: targetScrollTop,
        behavior: 'smooth', // 平滑滚动,替代jQuery的animate
      });
    }
  };

  return (
    <div>
      {/* 导航栏 */}
      <nav className="navbar navbar-expand-lg">
        <div className="container">
          <div className="collapse navbar-collapse" id="navbarNav">
            <ul className="navbar-nav align-items-lg-center ms-auto me-lg-5">
              {navItems.map((item, index) => (
                <li className="nav-item" key={item.target}>
                  <a
                    className={`nav-link click-scroll ${index === activeIndex ? 'active' : 'inactive'}`}
                    href={`#${item.target}`}
                    onClick={(e) => handleNavClick(e, item.target)}
                  >
                    {item.label}
                  </a>
                </li>
              ))}
            </ul>
          </div>
        </div>
      </nav>

      {/* 各个section */}
      <section ref={sectionRefs.section_1} className="home-section section-padding" id="section_1">
        {/* 这里填入Home区块内容 */}
      </section>
      <section ref={sectionRefs.section_2} className="about-section section-padding" id="section_2">
        {/* 这里填入About区块内容 */}
      </section>
      <section ref={sectionRefs.section_3} className="ecosystem-section section-padding" id="section_3">
        {/* 这里填入Ecosystem区块内容 */}
      </section>
    </div>
  );
};

export default App;

2. 关键改进点说明

  • 用useRef获取DOM元素:直接在React组件中绑定section的ref,确保能准确获取到渲染后的真实DOM元素,彻底避免jQuery找不到元素的问题。
  • useEffect管理滚动事件:在组件挂载后添加滚动监听,卸载时移除,符合React的生命周期,避免内存泄漏。
  • useState管理激活状态:通过状态更新导航项的active/inactive类,完全遵循React的数据流,避免直接操作DOM带来的同步问题。
  • 原生平滑滚动:用window.scrollTo配合behavior: 'smooth'替代jQuery的animate,无需依赖外部库,更符合React生态。

3. 额外注意事项

  • 移除原HTML中的jQuery脚本和相关逻辑,避免和React代码冲突。
  • 如果section是异步加载的(比如从接口获取内容后渲染),需要在useEffect的依赖数组中添加对应的加载状态,确保监听逻辑在组件完全加载完成后执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:35:01