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

当前回答

使用ES6 CLASS和React 15.x。X & lodash.debounce 我在这里使用React的refs,因为事件在内部失去了这个绑定。

class UserInput extends React.Component { constructor(props) { super(props); this.state = { userInput: "" }; this.updateInput = _.debounce(this.updateInput, 500); } updateInput(userInput) { this.setState({ userInput }); //OrderActions.updateValue(userInput);//do some server stuff } render() { return ( <div> <p> User typed: { this.state.userInput } </p> <input ref = "userValue" onChange = {() => this.updateInput(this.refs.userValue.value) } type = "text" / > </div> ); } } ReactDOM.render( < UserInput / > , document.getElementById('root') ); <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="root"></div>

其他回答

与其在debounce()中包装handleOnChange,不如在debounce()中包装回调函数中的ajax调用,从而不破坏事件对象。就像这样:

handleOnChange: function (event) {
   debounce(
     $.ajax({})
  , 250);
}

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

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

class MyComponent extends Component{
      constructor(props){
        super(props);
        this.handleChange = _.debounce(this.handleChange.bind(this),700);
      }; 
class UserListComponent extends Component {
    constructor(props) {
        super(props);
        this.searchHandler = this.keyUpHandler.bind(this);
        this.getData = this.getData.bind(this);
        this.magicSearch = this.magicSearch.bind(this,500);
    }
    getData = (event) => {
        console.log(event.target.value);
    }
    magicSearch = function (fn, d) {
        let timer;
        return function () {
            let context = this;
            clearTimeout(timer);
            timer = setTimeout(() => {
                fn.apply(context, arguments)
            }, d);
        }
    }
    keyUpHandler = this.magicSearch(this.getData, 500);
    render() {
        return (
             <input type="text" placeholder="Search" onKeyUp={this.searchHandler} />
        )
    }
}

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

与React挂钩反弹

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

不受控制的组件

你可以使用event.persist()方法。

下面是一个使用下划线_.debounce()的例子:

var SearchBox = React.createClass({

  componentWillMount: function () {
     this.delayedCallback = _.debounce(function (event) {
       // `event.target` is accessible now
     }, 1000);
  },

  onChange: function (event) {
    event.persist();
    this.delayedCallback(event);
  },

  render: function () {
    return (
      <input type="search" onChange={this.onChange} />
    );
  }

});

编辑:请看这个JSFiddle


控制组件

更新:上面的例子显示了一个不受控制的组件。我一直在使用受控元素,这里是上面的另一个例子,但没有使用event.persist()“欺骗”。

JSFiddle也是可用的。不带下划线的示例

var SearchBox = React.createClass({
    getInitialState: function () {
        return {
            query: this.props.query
        };
    },

    componentWillMount: function () {
       this.handleSearchDebounced = _.debounce(function () {
           this.props.handleSearch.apply(this, [this.state.query]);
       }, 500);
    },

    onChange: function (event) {
      this.setState({query: event.target.value});
      this.handleSearchDebounced();
    },

    render: function () {
      return (
        <input type="search"
               value={this.state.query}
               onChange={this.onChange} />
      );
    }
});


var Search = React.createClass({
    getInitialState: function () {
        return {
            result: this.props.query
        };
    },

    handleSearch: function (query) {
        this.setState({result: query});
    },

    render: function () {
      return (
        <div id="search">
          <SearchBox query={this.state.result}
                     handleSearch={this.handleSearch} />
          <p>You searched for: <strong>{this.state.result}</strong></p>
        </div>
      );
    }
});

React.render(<Search query="Initial query" />, document.body);

编辑:更新示例和JSFiddles到React 0.12

编辑:更新的例子,以解决Sebastien Lorber提出的问题

编辑:更新的jsfiddle不使用下划线和使用纯javascript debounce。