javascript - 无法使用 useState Hook 限制功能

标签 javascript reactjs lodash addeventlistener react-hooks

我正在尝试使用 lodash 库为我的 React 应用限制滚动事件“滚轮”,但没有成功。

我需要从滚动输入中监听 e.deltaY 以检测其滚动方向。为了添加一个监听器,我编写了一个接受事件名称和处理函数的 React Hook 。

基础实现

  const [count, setCount] = useState(0);

  const handleSections = () => {
    setCount(count + 1);
  };

  const handleWheel = _.throttle(e => {
    handleSections();
  }, 10000);

  useEventListener("wheel", handleWheel);

我的 useEventListener 钩子(Hook)

function useEventListener(e, handler, passive = false) {
  useEffect(() => {
    window.addEventListener(e, handler, passive);

    return function remove() {
      window.removeEventListener(e, handler);
    };
  });
}

工作演示:https://codesandbox.io/s/throttledemo-hkf7n

我的目标是限制此滚动事件,以便触发更少的事件并有几秒钟的时间以编程方式滚动我的页面(scrollBy(),par example)。 此时节流似乎不起作用,所以我同时收到很多滚动事件

最佳答案

当您可以在一个函数上调用 _.throttle() 时,您会得到一个“管理”原始函数调用的新函数。每当调用包装器函数时,包装器都会检查是否经过了足够的时间,如果是,则调用原始函数。

如果 _.throttle() 被多次调用,它会返回一个没有调用函数“历史记录”的新函数。然后它将一次又一次地调用原始函数。

在您的情况下,包装函数会在每次渲染时重新生成。使用 useCallback ( sandbox ) 包装对 _.throttle() 的调用:

const { useState, useCallback, useEffect } = React;

function useEventListener(e, handler, cleanup, passive = false) {
  useEffect(() => {
    window.addEventListener(e, handler, passive);

    return function remove() {
      cleanup && cleanup(); // optional specific cleanup for the handler
    
      window.removeEventListener(e, handler);
    };
  }, [e, handler, passive]);
}

const App = () => {
  const [count, setCount] = useState(0);

  const handleWheel = useCallback(_.throttle(() => {
    setCount(count => count + 1);
  }, 10000, { leading: false }), [setCount]);

  useEventListener("wheel", handleWheel, handleWheel.cancel); // add cleanup to cancel throttled calls

  return (
    <div className="App">
      <h1>Event fired {count} times</h1>
      <h2>It should add +1 to cout once per 10 seconds, doesn't it?</h2>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
  font-family: sans-serif;
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

关于javascript - 无法使用 useState Hook 限制功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56709727/

相关文章:

javascript - 延迟父组件渲染,直到所有子组件渲染 reactjs

javascript - 如何在react js中导入插件

javascript - 如何通过比较对象中具有不同元素的两个对象数组来过滤数组?

javascript - 我可以在 React Native 上向 this.props.children 添加额外的回调吗?

javascript - 对象数组的操作

javascript - 如何使用 lodash 创建嵌套过滤器

将onclick链接到.js到文件的javascript

javascript - 在 HTML 中按下按钮时无法显示图像

javascript - 如何在 React 中从父级重置表单

javascript - 当 src 为 dataURL 时指定视频的名称