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

当前回答

您可以使用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();

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

其他回答

I was searching for a solution to the same problem and came across this thread as well as some others but they had the same problem: if you are trying to do a handleOnChange function and you need the value from an event target, you will get cannot read property value of null or some such error. In my case, I also needed to preserve the context of this inside the debounced function since I'm executing a fluxible action. Here's my solution, it works well for my use case so I'm leaving it here in case anyone comes across this thread:

// at top of file:
var myAction = require('../actions/someAction');

// inside React.createClass({...});

handleOnChange: function (event) {
    var value = event.target.value;
    var doAction = _.curry(this.context.executeAction, 2);

    // only one parameter gets passed into the curried function,
    // so the function passed as the first parameter to _.curry()
    // will not be executed until the second parameter is passed
    // which happens in the next function that is wrapped in _.debounce()
    debouncedOnChange(doAction(myAction), value);
},

debouncedOnChange: _.debounce(function(action, value) {
    action(value);
}, 300)

Julen的解决方案有点难以阅读,这里有更清晰和准确的反应代码,供那些根据标题而不是问题的微小细节绊倒他的人使用。

Tl;dr版本:当你要更新到观察者发送调用一个调度方法,反过来实际上会通知观察者(或执行ajax等)

使用示例组件jsfiddle完成jsfiddle

var InputField = React.createClass({

    getDefaultProps: function () {
        return {
            initialValue: '',
            onChange: null
        };
    },

    getInitialState: function () {
        return {
            value: this.props.initialValue
        };
    },

    render: function () {
        var state = this.state;
        return (
            <input type="text"
                   value={state.value}
                   onChange={this.onVolatileChange} />
        );
    },

    onVolatileChange: function (event) {
        this.setState({ 
            value: event.target.value 
        });

        this.scheduleChange();
    },

    scheduleChange: _.debounce(function () {
        this.onChange();
    }, 250),

    onChange: function () {
        var props = this.props;
        if (props.onChange != null) {
            props.onChange.call(this, this.state.value)
        }
    },

});

有一个使用react钩子的简单方法。

步骤1:定义一个状态来维护搜索的文本

const [searchTerm, setSearchTerm] = useState('')

步骤2:使用useEffect捕获搜索Term中的任何变化

useEffect(() => {
  const delayDebounceFn = setTimeout(() => {
    if (searchTerm) {
      // write your logic here
    }
  }, 400)

  return () => clearTimeout(delayDebounceFn)
}, [searchTerm])

步骤3:编写一个函数来处理输入更改

function handleInputChange(value) {
  if (value) {
    setSearchTerm(value)
  }
}

就这些!在需要时调用此方法

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

与React挂钩反弹

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

今天遇到了这个问题。使用setTimeout和clearTimeout解决。

我将给出一个你可以适应的例子:

import React, { Component } from 'react'

const DEBOUNCE_TIME = 500

class PlacesAutocomplete extends Component {
  debounceTimer = null;

  onChangeHandler = (event) => {
    // Clear the last registered timer for the function
    clearTimeout(this.debounceTimer);

    // Set a new timer
    this.debounceTimer = setTimeout(
      // Bind the callback function to pass the current input value as arg
      this.getSuggestions.bind(null, event.target.value), 
      DEBOUNCE_TIME
    )
  }

  // The function that is being debounced
  getSuggestions = (searchTerm) => {
    console.log(searchTerm)
  }

  render() {
    return (
      <input type="text" onChange={this.onChangeHandler} />
    )
  }
}

export default PlacesAutocomplete

你也可以在它自己的函数组件中重构它:

import React from 'react'

function DebouncedInput({ debounceTime, callback}) {
  let debounceTimer = null
  return (
    <input type="text" onChange={(event) => {
      clearTimeout(debounceTimer);

      debounceTimer = setTimeout(
        callback.bind(null, event.target.value), 
        debounceTime
      )
    }} />
  )
}

export default DebouncedInput

像这样使用它:

import React, { Component } from 'react'
import DebouncedInput from '../DebouncedInput';

class PlacesAutocomplete extends Component {
  debounceTimer = null;

  getSuggestions = (searchTerm) => {
    console.log(searchTerm)
  }

  render() {
    return (
      <DebouncedInput debounceTime={500} callback={this.getSuggestions} />
    )
  }
}

export default PlacesAutocomplete