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

React中如何更新document.body.offsetHeight并实现滚动加载?

Fixing Infinite Scroll: Getting Updated document.body.offsetHeight After Loading Data

Great question! This is a super common gotcha with infinite scroll in React—your scroll listener is checking the body height before React has finished rendering the new data you just loaded, so it’s still using the old value. Let’s walk through the fixes step by step:

1. First, Clean Up Your Scroll Listener (Critical!)

Right now, your effect isn’t removing the scroll listener when the component unmounts or when state changes. This leads to duplicate listeners firing, which can cause weird behavior like multiple load requests at once. Update your effect to include a cleanup function:

React.useEffect(() => { 
  const handleScroll = () => { 
    if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight && !state.more) { 
      getAscii(state.page, 21, dispatch) 
      console.log("you're at the bottom of the page", state.page) 
    } 
  }

  window.addEventListener('scroll', handleScroll)
  // Clean up the listener when component unmounts or state changes
  return () => window.removeEventListener('scroll', handleScroll)
}, [state])

2. Wait for the DOM to Update Before Checking Height

React updates the DOM asynchronously after state changes. When your getAscii call finishes and updates state, the new data hasn’t rendered yet—so document.body.offsetHeight is still the old value. Use requestAnimationFrame to delay your height check until the next browser repaint, which ensures the DOM has updated:

const handleScroll = () => {
  // Exit early if we're already loading more data
  if (state.more) return;

  requestAnimationFrame(() => {
    // Add a small buffer (10px) to avoid missing the bottom due to browser rendering quirks
    const isAtBottom = (window.innerHeight + window.scrollY) >= document.body.offsetHeight - 10;
    if (isAtBottom) {
      getAscii(state.page, 21, dispatch);
      console.log("you're at the bottom of the page", state.page);
    }
  });
};

3. Use a Ref for More Reliable Height Tracking (Even Better!)

Relying on document.body.offsetHeight can be flaky if your page has fixed headers, footers, or other elements that affect the body’s height. Instead, attach a ref directly to your list container and check its height—this gives you a precise measurement of your scrollable content:

// Create a ref for your list container
const listContainerRef = React.useRef(null);

const handleScroll = () => {
  if (state.more) return;

  requestAnimationFrame(() => {
    const container = listContainerRef.current;
    if (!container) return;

    // Calculate if we've reached the bottom of the list container
    const containerBottom = container.offsetTop + container.offsetHeight;
    const isAtBottom = (window.innerHeight + window.scrollY) >= containerBottom - 10;
    
    if (isAtBottom) {
      getAscii(state.page, 21, dispatch);
      console.log("you're at the bottom of the page", state.page);
    }
  });
};

// Attach the ref to your list in JSX
return (
  <div ref={listContainerRef}>
    {/* Your rendered list items go here */}
    {state.data.map(item => <div key={item.id}>{item.content}</div>)}
  </div>
);

4. Double-Check Your state.more Flag

Make sure your getAscii function is correctly updating the more state to prevent duplicate requests:

  • When you start loading data, set more: true
  • When the data finishes loading (and is added to your state), set more: false

This ensures that while new data is being fetched, your scroll listener won’t trigger another request before the DOM has a chance to update.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:53:26