手柄滚动中的设置状态显示了先前的状态-响应钩子,油门和redux

时间:2020-07-06 08:15:00

标签: reactjs react-redux react-hooks throttling

我当前正在尝试在导航栏中获取导航项,以在用户滚动到页面的某些部分时切换类。我的代码使用的是redux,因此当用户滚动到页面的x部分时,我向redux分配了一个操作,该操作随后更改了导航栏的类。但是,随着用户滚动,我的代码对redux的调用太多了,这减慢了用户在导航栏中看到更改的速度。我尝试使用节流阀限制设置Redux状态的调用次数。但这只起作用了一点(仍然有太多的呼叫在进行)。这是我用于更多上下文的代码:

// on scroll change active classes in navbar
useEffect(() => {
  const handleScroll = (event) => {
    const throttleFunc = throttle(9999999, false, () => {
      // fill info
      if (
        props.readCarefullySect.current.getBoundingClientRect().top > 150 &&
        props.stageData.navTwo !== "active" &&
        !stage.fillInfo
      ) {
        setStage({
          fillInfo: true,
          readCarefully: false,
          signature: false,
        });
        props.activeFillInfo();
      }
      // signature
      else if (
        props.readCarefullySect.current.getBoundingClientRect().top < -3555 &&
        props.stageData.navFour !== "active" &&
        !stage.signature
      ) {
        setStage({
          fillInfo: false,
          readCarefully: false,
          signature: true,
        });
        props.activeSignature();
      }
      // read carefully
      else if (
        props.readCarefullySect.current.getBoundingClientRect().top <= 150 &&
        props.readCarefullySect.current.getBoundingClientRect().top >= -3555 &&
        props.stageData.navThree !== "active" &&
        !stage.readCarefully
      ) {
        setStage({
          fillInfo: false,
          readCarefully: true,
          signature: false,
        });
        console.log("stage in read carefully", stage);
        props.activeReadCarefully();
      }
    });

    throttleFunc();
  };

  window.addEventListener("scroll", handleScroll);
}, [props, stage]);

因为节流阀似乎不像我想的那样起作用,所以我尝试将每个称为“ stage”的对象添加到每个条件中,该对象应根据用户滚动到的位置而改变。想法是,如果阶段已经设置为等于用户所在的部分,则不应将操作分派到redux

当我在每个if语句中进行console.log(stage)时,如果if语句在正确的位置被命中,但是该阶段表明用户所在的上一个位置的正确/错误。例如,我的应用程序的阶段是(从上到下)填充信息,仔细阅读,签名,当用户从填充信息滚动以仔细阅读时,当前阶段为:

{ fillInfo: true, readCarefully: false, signature: false }

但应等于

{ fillInfo: false, readCarefully: true, signature: false }

同样,如果用户再次向上滚动,则阶段等于

{ fillInfo: false, readCarefully: true, signature: false }

但应等于

{ fillInfo: true, readCarefully: false, signature: false }

一定是我在做/不做的事情导致了问题。我对React还是相当陌生,因此非常感谢您的见识

1 个答案:

答案 0 :(得分:0)

我猜你的节流功能是一个反跳功能,下面是如何执行此操作的示例,当效果再次运行时,还需要删除事件监听器:

//call function if inactive for time in milliseconds
const debounce = (fn, time = 1000) => {
  let timeOut;
  return (...args) => {
    clearTimeout(timeOut);
    timeOut = setTimeout(() => fn(...args), time);
  };
};
const App = () => {
  const [scrollPos, setScrollPos] = React.useState();
  React.useEffect(() => {
    const handleScroll = debounce(() =>
      setScrollPos(Math.floor(window.scrollY))
    );

    window.addEventListener('scroll', handleScroll);
    //clean up, scroll listener
    return () => window.removeEventListener(handleScroll);
  }, []);

  return (
    <ul>
      {new Array(100).fill('').map((_, i) => (
        <li key={i}>
          scroll position: {scrollPos}
        </li>
      ))}
    </ul>
  );
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>