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

React中使用useRef与window滚动事件时出现undefined报错问题

解决Sticky导航栏滚动时的undefined报错问题

问题原因

你遇到的undefined报错主要来自两个场景:

  • 组件初始化阶段,toolbarRef.current还未指向DOM元素时,scroll事件就已触发,此时访问toolbarRef.current.getBoundingClientRect()会直接报错。
  • 直接给window绑定scroll监听后,组件卸载时未移除该监听,不仅会造成内存泄漏,还会在组件卸载后触发事件时,访问已不存在的ref导致报错。

修复方案

使用React的useEffect管理scroll事件的生命周期,确保监听仅在组件挂载后添加、卸载时移除;同时在事件处理逻辑里先判断ref是否有效,再执行后续操作。

修改后的代码

import { memo, useRef, useEffect } from 'react';
import styles from '../styles/NotesToolbar.module.css';
import FilterSelect from './FilterSelect';
import NotesCounter from './NotesCounter';

const NotesToolbar = () => {
  const toolbarRef = useRef();

  useEffect(() => {
    const handleScroll = () => {
      // 先确认ref已关联DOM元素
      if (!toolbarRef.current) return;
      
      const rect = toolbarRef.current.getBoundingClientRect();
      if (rect.top <= 0) {
        toolbarRef.current.classList.add(styles.ToolbarSticky);
      } else {
        toolbarRef.current.classList.remove(styles.ToolbarSticky);
      }
    };

    // 组件挂载后添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 组件卸载时清除监听
    return () => window.removeEventListener('scroll', handleScroll);
  }, []); // 空依赖数组确保监听只绑定一次

  return (
    <div className={styles.Toolbar} ref={toolbarRef}>
      <div className={styles.ToolbarLeft}>
        <FilterSelect />
      </div>
      <div className={styles.ToolbarRight}>
        <NotesCounter />
      </div>
    </div>
  );
};

export default memo(NotesToolbar);

关键说明

  • useEffect的空依赖数组保证监听仅在组件挂载时初始化一次,避免重复绑定;返回的清理函数会在组件卸载时自动移除监听。
  • 事件处理函数里先判断toolbarRef.current是否存在,从根源避免undefined报错。
  • 将handleScroll定义在useEffect内部,确保它能正确捕获最新的ref引用,符合React Hooks的使用规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:03:24