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

当前回答

今天遇到了这个问题。使用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

其他回答

我们需要将setter传递给debpublished方法:

以下是StackBlitz的一个例子:

import React from "react";
import debounce from "lodash/debounce";

export default function App() {
  const [state, setState] = React.useState({
    debouncedLog: ""
  });

  const debouncedLog = React.useCallback(
    debounce((setState, log) => {
      setState(prevState => ({
        ...prevState,
        debouncedLog: log
      }));
    }, 500),
    []
  );

  const onChange = React.useCallback(({ target: { value: log } }) => {
    debouncedLog(setState, log); // passing the setState along...
  }, []);
  return (
    <div>
      <input onChange={onChange} style={{ outline: "1px blue solid" }} />

      <pre>Debounced Value: {state.debouncedLog}</pre>
    </div>
  );
}

祝你好运…

现在,React和React Native在2019年底有了另一个解决方案:

react-debounce-component

<input>
<Debounce ms={500}>
  <List/>
</Debounce>

它是一个组件,易于使用,体积小,支持广泛

例子:

import React from 'react';
import Debounce from 'react-debounce-component';

class App extends React.Component {
  constructor (props) {
    super(props);
    this.state = {value: 'Hello'}
  }
  render () {
    return (
      <div>
        <input value={this.state.value} onChange={(event) => {this.setState({value: event.target.value})}}/>
        <Debounce ms={1000}>
          <div>{this.state.value}</div>
        </Debounce>
      </div>
    );
  }
}

export default App;

我是这个组件的创建者

我在这个问题下找不到任何答案,提到我正在使用的方法,所以只想在这里提供一个替代解决方案,我认为这是最适合我的用例。

如果您正在使用流行的react钩子工具包库react-use,那么有一个名为useDebounce()的实用工具钩子,它以一种相当优雅的方式实现了谴责逻辑。

const [query, setQuery] = useState('');

useDebounce(
  () => {
    emitYourOnDebouncedSearchEvent(query);
  },
  2000,
  [query]
);

return <input onChange={({ currentTarget }) => setQuery(currentTarget.value)} />

有关详细信息,请直接检查库的github页面。

https://github.com/streamich/react-use/blob/master/docs/useDebounce.md

如果你只需要从事件对象中获取DOM输入元素,解决方案就简单多了——只需要使用ref。注意,这需要下划线:

class Item extends React.Component {
    constructor(props) {
        super(props);
        this.saveTitle = _.throttle(this.saveTitle.bind(this), 1000);
    }
    saveTitle(){
        let val = this.inputTitle.value;
        // make the ajax call
    }
    render() {
        return <input 
                    ref={ el => this.inputTitle = el } 
                    type="text" 
                    defaultValue={this.props.title} 
                    onChange={this.saveTitle} />
    }
}

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

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

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