Next.js中如何监听document滚动高度变化,解决document未定义报错
问题原因
Next.js 默认开启服务端渲染/静态生成能力,服务端运行代码时不存在document、window等浏览器全局对象,你原代码直接把document.documentElement.scrollHeight放在 useEffect 依赖数组中,服务端初始化执行依赖解析时就会直接抛出未定义错误。
最优实现方案
用ResizeObserver监听文档根元素的尺寸变化来感知滚动高度变更,性能远优于定时轮询方案,同时做好浏览器环境判断避免服务端执行报错。
完整代码实现
import { useEffect, useRef, useState } from 'react' // 组件内部逻辑 const [docScrollHeight, setDocScrollHeight] = useState(0) const resizeObserverRef = useRef(null) // 监听文档滚动高度变化 useEffect(() => { // 服务端环境直接跳过 if (typeof window === 'undefined') return resizeObserverRef.current = new ResizeObserver((entries) => { for (const entry of entries) { setDocScrollHeight(entry.target.scrollHeight) } }) // 监听根元素尺寸变化,也可以替换为你实际内容容器的DOM节点,监听更精准 resizeObserverRef.current.observe(document.documentElement) // 组件卸载清理观察者,避免内存泄漏 return () => { resizeObserverRef.current?.disconnect() } }, []) // 执行自动滚动逻辑 useEffect(() => { if (typeof window === 'undefined') return if (postdata.isLoading || postProgress == null) return const heightWin = docScrollHeight - document.documentElement.clientHeight const offset = postProgress / 100 const offsetScroll = offset * heightWin window.scrollTo(0, offsetScroll) }, [postinfo.isLoading, postdata.isLoading, postProgress, docScrollHeight])
说明
- 所有浏览器API调用都添加了环境判断守卫,完全规避服务端执行报错问题
- 依赖数组不再直接引用document相关属性,避免服务端解析依赖阶段触发错误
- ResizeObserver会在元素尺寸变更时自动触发回调,无多余性能开销
内容的提问来源于stack exchange,提问作者Aadhit Shanmugam
相关产品推荐
相关产品推荐

