使用 useState 和 useEffect 每 8 秒更新一次滚动位置?

update scroll position every 8 seconds with useState and useEffect?

我正在为我的 Web 应用程序使用 next js。我想编写使用 useState 更新滚动位置的函数。出于某种原因,useState 没有正确更新自身,因为我还需要计算函数的最大值。这是我的代码:

const [lazyProgress,setLazyProgress] = useState(0);
const [lazyProgressMax,setLazyProgressMax] = useState(0);


function lazyProgressUpdate(){
        const scrollTotal = document.documentElement.scrollTop;
        const heightWin = document.documentElement.scrollHeight - document.documentElement.clientHeight;
        const scroll = scrollTotal / heightWin * 100;

        setLazyProgress(scroll);
        if(lazyProgress > lazyProgressMax){
        setLazyProgressMax(lazyProgress);
    }
    console.log(lazyProgress,lazyProgressMax)

}

useEffect(()=>{

  const timer = setInterval(()=>{
          lazyProgressUpdate();
      },8000);
      return ()=>{
      clearInterval(timer);
      }
  },[]);

在上面的代码片段中,lazyProgress 和 lazyProgressMax 在函数中始终为 0。所以他们都没有更新。

我该如何解决这个问题

问题

您遇到的问题实际上是 setInterval 回调中状态的陈旧封闭。此回调关闭初始状态,因此它会看到所有内容。

解决方案

排队滚动更新并使用单独的 useEffect 挂钩,依赖 lazyProgress 到 check/set lazyProgressMax 状态。

const [lazyProgress, setLazyProgress] = useState(0);
const [lazyProgressMax, setLazyProgressMax] = useState(0);

function lazyProgressUpdate(){
  const scrollTotal = document.documentElement.scrollTop;
  const heightWin = document.documentElement.scrollHeight - document.documentElement.clientHeight;
  const scroll = scrollTotal / heightWin * 100;

  setLazyProgress(scroll); // <-- (1) update lazyProgress state
}

useEffect(() => {
  const timer = setInterval(() => {
    lazyProgressUpdate();
  }, 8000);
  return () => {
    clearInterval(timer);
  }
},[]);

useEffect(() => {
  setLazyProgressMax(lazyProgressMax => { // <-- (3) functional state update
    if (lazyProgress > lazyProgressMax) {
      return lazyProgress; // <-- (4a) return new lazyProgress value
    }
    return lazyProgressMax; // <-- (4b) or previous state
  });
}, [lazyProgress]); // <-- (2) lazyProgress as dependency

您需要在 useEffect 中创建函数,以防万一函数不再需要。

以下代码指导如何在useEffect中创建函数以及如何清除创建的间隔。


    useEffect(()=>{

      const lazyProgressUpdate = () => {
         // function logic here
      }

      const timer = setInterval(() => {
             lazyProgressUpdate()
          }, 8000);
      
      return () => {
          clearInterval(timer);
      }
    },[]);