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
相关产品推荐
相关产品推荐

