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

当前回答

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} />
        )
    }
}

其他回答

简单有效 https://www.npmjs.com/package/use-debounce use-debounce

import { useDebouncedCallback } from 'use-debounce';

function Input({ defaultValue }) {
  const [value, setValue] = useState(defaultValue);
  const debounced = useDebouncedCallback(
    (value) => {
      setValue(value);
    },
    // delay
    1000
  );

  return (
    <div>
      <input defaultValue={defaultValue} onChange={(e) => debounced(e.target.value)} />
      <p>Debounced value: {value}</p>
    </div>
  );
}

如果你只需要从事件对象中获取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} />
    }
}

你试过吗?

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

FYI

这是另一个PoC实现:

没有任何库(例如lodash)用于debound 使用React Hooks API

我希望它能帮助你:)

import React, { useState, useEffect, ChangeEvent } from 'react';

export default function DebouncedSearchBox({
  inputType,
  handleSearch,
  placeholder,
  debounceInterval,
}: {
  inputType?: string;
  handleSearch: (q: string) => void;
  placeholder: string;
  debounceInterval: number;
}) {
  const [query, setQuery] = useState<string>('');
  const [timer, setTimer] = useState<NodeJS.Timer | undefined>();

  useEffect(() => {
    if (timer) {
      clearTimeout(timer);
    }
    setTimer(setTimeout(() => {
      handleSearch(query);
    }, debounceInterval));
  }, [query]);

  const handleOnChange = (e: ChangeEvent<HTMLInputElement>): void => {
    setQuery(e.target.value);
  };

  return (
    <input
      type={inputType || 'text'}
      className="form-control"
      placeholder={placeholder}
      value={query}
      onChange={handleOnChange}
    />
  );
}

至于2021年6月,您可以简单地实现xnimorz解决方案:https://github.com/xnimorz/use-debounce

import { useState, useEffect, useRef } from "react";
// Usage
function App() {
  // State and setters for ...
  // Search term
  const [searchTerm, setSearchTerm] = useState("");
  // API search results
  const [results, setResults] = useState([]);
  // Searching status (whether there is pending API request)
  const [isSearching, setIsSearching] = useState(false);
  // Debounce search term so that it only gives us latest value ...
  // ... if searchTerm has not been updated within last 500ms.
  // The goal is to only have the API call fire when user stops typing ...
  // ... so that we aren't hitting our API rapidly.
  const debouncedSearchTerm = useDebounce(searchTerm, 500);
  // Effect for API call
  useEffect(
    () => {
      if (debouncedSearchTerm) {
        setIsSearching(true);
        searchCharacters(debouncedSearchTerm).then((results) => {
          setIsSearching(false);
          setResults(results);
        });
      } else {
        setResults([]);
        setIsSearching(false);
      }
    },
    [debouncedSearchTerm] // Only call effect if debounced search term changes
  );
  return (
    <div>
      <input
        placeholder="Search Marvel Comics"
        onChange={(e) => setSearchTerm(e.target.value)}
      />
      {isSearching && <div>Searching ...</div>}
      {results.map((result) => (
        <div key={result.id}>
          <h4>{result.title}</h4>
          <img
            src={`${result.thumbnail.path}/portrait_incredible.${result.thumbnail.extension}`}
          />
        </div>
      ))}
    </div>
  );
}
// API search function
function searchCharacters(search) {
  const apiKey = "f9dfb1e8d466d36c27850bedd2047687";
  return fetch(
    `https://gateway.marvel.com/v1/public/comics?apikey=${apiKey}&titleStartsWith=${search}`,
    {
      method: "GET",
    }
  )
    .then((r) => r.json())
    .then((r) => r.data.results)
    .catch((error) => {
      console.error(error);
      return [];
    });
}
// Hook
function useDebounce(value, delay) {
  // State and setters for debounced value
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(
    () => {
      // Update debounced value after delay
      const handler = setTimeout(() => {
        setDebouncedValue(value);
      }, delay);
      // Cancel the timeout if value changes (also on delay change or unmount)
      // This is how we prevent debounced value from updating if value is changed ...
      // .. within the delay period. Timeout gets cleared and restarted.
      return () => {
        clearTimeout(handler);
      };
    },
    [value, delay] // Only re-call effect if value or delay changes
  );
  return debouncedValue;
}