NextJS中自定义useScrollPosition Hook失效,无法触发下一页数据获取
解决方案
你的自定义useScrollPosition Hook失效的核心原因是监听了错误的滚动容器:你监听的是window的scroll事件,但实际页面中滚动的是Feed组件所在的<div className="h-full">容器(而非整个窗口),导致window的滚动事件从未触发,scrollPosition自然不会更新。
同时,原Hook中未缓存handleScroll函数,在组件重渲染时可能出现事件监听的清理/绑定不一致问题,需要用useCallback优化。
步骤1:修改useScrollPosition Hook
import { useState, useEffect, useCallback, RefObject } from 'react'; function useScrollPosition(elementRef?: RefObject<HTMLElement>) { const [scrollPosition, setScrollPosition] = useState(0); // 用useCallback缓存滚动处理函数,确保依赖变化时才更新 const handleScroll = useCallback(() => { const target = elementRef?.current || window; let totalScrollableHeight: number; let currentScrollTop: number; if (target === window) { totalScrollableHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight; currentScrollTop = document.body.scrollTop || document.documentElement.scrollTop; } else { totalScrollableHeight = target.scrollHeight - target.clientHeight; currentScrollTop = target.scrollTop; } // 处理无滚动空间的情况,避免NaN if (totalScrollableHeight <= 0) { setScrollPosition(0); return; } const scrolledPercentage = (currentScrollTop / totalScrollableHeight) * 100; setScrollPosition(scrolledPercentage); }, [elementRef]); useEffect(() => { const target = elementRef?.current || window; // 添加passive: true提升滚动性能(无需阻止默认行为) target.addEventListener('scroll', handleScroll, { passive: true }); return () => { target.removeEventListener('scroll', handleScroll); }; }, [elementRef, handleScroll]); return scrollPosition; }
步骤2:在Feed组件中绑定滚动容器的Ref
// 导入useRef import { useState, useEffect, useRef } from 'react'; export const Feed = () => { // ...其他代码保持不变 // 创建滚动容器的Ref const feedScrollRef = useRef<HTMLDivElement>(null); // 将Ref传入自定义Hook const scrollPosition = useScrollPosition(feedScrollRef); // ...其他代码保持不变 return ( // 将Ref绑定到实际滚动的容器上 <div className="h-full" ref={feedScrollRef}> {tweets.map((fullTweet) => ( <TweetView tweetData={{ ...fullTweet }} key={fullTweet.tweet.id} input={{ limit: LIMIT }} /> ))} </div> ); };
额外说明
- 如果你的页面确实是整个窗口滚动(而非内部容器),可以不传入
elementRef,Hook会自动监听window的滚动事件。 - 添加
passive: true是滚动事件监听的最佳实践,能避免浏览器的滚动卡顿问题。 - 处理
totalScrollableHeight <= 0的情况,防止出现NaN值导致状态异常。
内容的提问来源于stack exchange,提问作者TheInfamousGrim
相关产品推荐
相关产品推荐

