如何在React.js中执行debounce ?

我想撤消handleOnChange。

我尝试debounce(这。handleOnChange, 200)但它不起作用。

function debounce(fn, delay) {
  var timer = null;
  return function() {
    var context = this,
      args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(context, args);
    }, delay);
  };
}

var SearchBox = React.createClass({
  render: function() {
    return <input type="search" name="p" onChange={this.handleOnChange} />;
  },

  handleOnChange: function(event) {
    // make ajax call
  }
});

当前回答

避免使用event.persist()——你想让React回收合成事件。我认为无论你使用类还是钩子,最干净的方法是将回调函数分成两部分:

没有deboundation的回调 只使用您需要的事件片段调用已撤销的函数(这样合成的事件就可以循环使用)

handleMouseOver = throttle(target => {
  console.log(target);
}, 1000);

onMouseOver = e => {
  this.handleMouseOver(e.target);
};

<div onMouseOver={this.onMouseOver} />

功能

const handleMouseOver = useRef(throttle(target => {
  console.log(target);
}, 1000));

function onMouseOver(e) {
  handleMouseOver.current(e.target);
}

<div onMouseOver={this.onMouseOver} />

注意,如果你的handleMouseOver函数从组件中使用状态,你应该使用usemo而不是useRef,并将它们作为依赖项传递,否则你将使用过时的数据(当然不适用于类)。

其他回答

您可以使用Lodash debounce https://lodash.com/docs/4.17.5#debounce方法。它简单有效。

import * as lodash from lodash;

const update = (input) => {
    // Update the input here.
    console.log(`Input ${input}`);     
}

const debounceHandleUpdate = lodash.debounce((input) => update(input), 200, {maxWait: 200});

doHandleChange() {
   debounceHandleUpdate(input);
}

您还可以使用下面的方法取消debounce方法。

this.debounceHandleUpdate.cancel();

希望对你有所帮助。干杯! !

这里有一个工作的TypeScript示例,供那些使用TS并想要debounce async函数的人使用。

function debounce<T extends (...args: any[]) => any>(time: number, func: T): (...funcArgs: Parameters<T>) => Promise<ReturnType<T>> {
     let timeout: Timeout;

     return (...args: Parameters<T>): Promise<ReturnType<T>> => new Promise((resolve) => {
         clearTimeout(timeout);
         timeout = setTimeout(() => {
             resolve(func(...args));
         }, time)
     });
 }

2019:使用“useCallback”反应钩子

在尝试了许多不同的方法之后,我发现使用useCallback是解决在onChange事件中使用debounce的多次调用问题的最简单和最有效的方法。

根据Hooks API文档,

useCallback返回回调的一个记忆版本,只有当其中一个依赖项发生变化时才会发生变化。

将空数组作为依赖项传递可以确保只调用一次回调。下面是一个简单的实现:

import React, { useCallback } from "react";
import { debounce } from "lodash";

const handler = useCallback(debounce(someFunction, 2000), []);
    
const onChange = (event) => {
    // perform any event related action here
    
    handler();
 };

避免使用event.persist()——你想让React回收合成事件。我认为无论你使用类还是钩子,最干净的方法是将回调函数分成两部分:

没有deboundation的回调 只使用您需要的事件片段调用已撤销的函数(这样合成的事件就可以循环使用)

handleMouseOver = throttle(target => {
  console.log(target);
}, 1000);

onMouseOver = e => {
  this.handleMouseOver(e.target);
};

<div onMouseOver={this.onMouseOver} />

功能

const handleMouseOver = useRef(throttle(target => {
  console.log(target);
}, 1000));

function onMouseOver(e) {
  handleMouseOver.current(e.target);
}

<div onMouseOver={this.onMouseOver} />

注意,如果你的handleMouseOver函数从组件中使用状态,你应该使用usemo而不是useRef,并将它们作为依赖项传递,否则你将使用过时的数据(当然不适用于类)。

一个漂亮干净的解决方案,不需要任何外部依赖:

与React挂钩反弹

它使用了一个自定义加上useEffect React钩子和setTimeout / clearTimeout方法。