如何在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
  }
});

当前回答

看点:

import {useState} from "react";

const useDebounce = ({defaultTimeout = 250, defaultIdentifier = 'default'} = {}) => {

    const [identifiers, setIdentifiers] = useState({[defaultIdentifier]: null});

    return ({fn = null, identifier = defaultIdentifier, timeout = defaultTimeout} = {}) => {
        if (identifiers.hasOwnProperty(identifier)) clearTimeout(identifiers[identifier]);
        setIdentifiers({...identifiers, [identifier]: setTimeout(fn, timeout)});
    };
};

export default useDebounce;

并在任何地方使用它(在同一个文件中使用标识符以防止并发),例如:

const debounce = useDebounce();

const handlerA = () => {
    debounce({fn: () => console.log('after 2000ms of last call with identifier A'), identifier: 'A', timeout: 2000});
};

const handlerB = () => {
    debounce({fn: () => console.log('after 1500ms of last call with identifier B'), identifier: 'B', timeout: 1500});
};

其他回答

这里已经有很多好的信息了,但为了简洁。这对我很有用……

import React, {Component} from 'react';
import _ from 'lodash';

class MyComponent extends Component{
      constructor(props){
        super(props);
        this.handleChange = _.debounce(this.handleChange.bind(this),700);
      }; 

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();
 };

你试过吗?

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) {
    debounce(\\ Your handleChange code , 200);
  }
});

我发现Justin Tulk的这篇文章很有帮助。在经过几次尝试后,人们会认为这是react/redux更正式的方式,结果显示它失败了,因为react的合成事件池。然后,他的解决方案使用一些内部状态来跟踪在输入中更改/输入的值,在setState之后使用一个回调,调用一个throttled/ deboundredux动作,实时显示一些结果。

import React, {Component} from 'react'
import TextField from 'material-ui/TextField'
import { debounce } from 'lodash'

class TableSearch extends Component {

  constructor(props){
    super(props)

    this.state = {
        value: props.value
    }

    this.changeSearch = debounce(this.props.changeSearch, 250)
  }

  handleChange = (e) => {
    const val = e.target.value

    this.setState({ value: val }, () => {
      this.changeSearch(val)
    })
  }

  render() {

    return (
        <TextField
            className = {styles.field}
            onChange = {this.handleChange}
            value = {this.props.value}
        />
    )
  }
}

下面是一个使用@Abra方法封装在函数组件中的代码片段 (我们使用织物的UI,只是用一个简单的按钮替换它)

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

import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';

const debounceTimeInMS = 2000;

export const PrimaryButtonDebounced = (props) => {

    const debouncedOnClick = debounce(props.onClick, debounceTimeInMS, { leading: true });

    const clickHandlerDebounced = useCallback((e, value) => {

        debouncedOnClick(e, value);

    },[]);

    const onClick = (e, value) => {

        clickHandlerDebounced(e, value);
    };

    return (
        <PrimaryButton {...props}
            onClick={onClick}
        />
    );
}