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

Next.js搭配react-odometerjs与visibility-sensor报getBoundingClientRect错误如何解决

Next.js 搭配 react-odometerjs 与 react-visibility-sensor 报错修复方案

错误原因

报错的核心原因是 react-visibility-sensor 组件需要向直接子元素注入 ref,以此获取DOM节点的位置信息判断元素是否进入视口。但你直接将动态导入的 react-odometerjs 组件作为它的直接子节点,该组件未做ref转发处理,导致传感器无法拿到有效DOM节点,调用getBoundingClientRect方法时抛出空引用错误。

修复方法

只需要给 <Odometer> 组件外层包裹一层原生DOM元素(比如div)作为 react-visibility-sensor 的直接子元素即可,原生DOM元素天然支持ref绑定,传感器可以正常获取节点信息。

如果需要优化逻辑,也可以将计数器数值更新的逻辑放到元素可见之后触发,更符合滚动到对应位置才播放计数动画的需求。

修复后完整代码如下:

import { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import "odometer/themes/odometer-theme-default.css";
const Odometer = dynamic(import("react-odometerjs"), {
  ssr: false,
  loading: () => 0
});
import VisibilitySensor from "react-visibility-sensor";

export default function IndexPage() {
  const [odometerValue, setOdometerValue] = useState(0);
  const [view, setView] = useState(false);
  const onVisibilityChange = (isVisible) => {
    if (isVisible) {
      setView(true);
    }
  };

  // 优化:元素可见后再更新数值,触发计数动画
  useEffect(() => {
    if (view) {
      setOdometerValue(500);
    }
  }, [view]);

  return (
    <VisibilitySensor onChange={onVisibilityChange} offset={8} delayedCall>
      {/* 新增外层div作为VisibilitySensor的直接子元素 */}
      <div>
        <Odometer
          value={view ? odometerValue : 0}
          format="(,ddd)"
          theme="default"
        />
      </div>
    </VisibilitySensor>
  );
}

注意事项

  • 你之前对react-odometerjs的动态导入配置是正确的,因为odometer底层依赖浏览器window对象,必须关闭SSR避免服务端渲染时报错。
  • 外层div可以根据你的布局需求加样式,不会影响odometer的显示效果和传感器的可见性判断逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 04:12:01