在 React 中,有没有一种方法可以仅在有人停止输入时才提交我的搜索请求?

In React, is there a way I can submit my search request only when someone stops typing?

我正在使用 React 16.13.0。我有一个搜索框,人们可以在其中输入内容并希望在输入时看到结果...

return (
  <div className="searchForm">
    <input
      type="text"
      placeholder="Search"
      value={this.state.searchTerm}
      onChange={this.handleChange}
    />

我使用以下函数来处理人们键入时检索结果...

  handleChange(event) {
    const query = event.target.value;
    if (!query) {
      this.setState({ searchTerm: query, searchResults: [] });
    } else {
      this.setState({ searchTerm: query, loading: true }, () => {
        this.doSearch(query);
      });
    }
  }

  doSearch = (query) => {
    const searchUrl = "/coops/?contains=" + encodeURIComponent(query);
    fetch(searchUrl, {
      method: "GET",
    })
      .then((response) => response.json())
      .then((data) => {
        if (query === this.state.searchTerm) {
          this.setState({
            searchResults: data,
            loading: false,
          });
        }
      });
  };

我正在努力减少 made/processed 的网络通话量。如果有人以相当快的方式输入像“res”这样的字符串,他们可能不关心“r”或“re”的结果,所以我想知道,如果有新的请求,我是否可以通过某种方式取消请求我的搜索框中输入了字母?或者仅在某人停止输入至少 100 毫秒后才执行搜索(不确定这是否足够,但决定选择任意数量)?

您可以通过setTimeout延迟搜索。每当捕获到新输入时,只需清除超时。如果定时器超时,去执行请求

handleChange = (e) => {
    this.setState(
        {
            searchTerm: e.target.value
        },
        () => {
            try {
                clearInterval(window.xhrSearchTimer);
            } catch (e) {
                console.log(`no timeout initialized`);
            }

            window.xhrSearchTimer = window.setTimeout(() => {
                this.doSearch(this.state.searchTerm);
            }, 1000); // arbitrary value
        }
    );
};

doSearch = () => {
    alert(`Now searching for ${this.state.searchTerm}`);
};

https://codesandbox.io/s/loving-sid-hb0nr?file=/src/App.js:139-622

您所追求的通常称为去抖动。有许多库实现了这个功能,包括。 lodash 和下划线。 例如,在 lodash 中,您可以执行以下操作:

      onChange={e => debouncedHandler(e, this.handleChange)}

并定义了以下 outside 组件:

const debouncedHandler = _.debounced((e, handler) => handler(e), 100);

在组件内部声明去抖功能是一个常见的陷阱。这将 not 工作,因为反应在每次更改时重新运行该代码,因此 re-created 去抖功能,因此不会发生去抖动。因此,在组件外部定义去抖功能很重要。


更新:我之前的代码有错误。现在已经修好了,我想。我还没有测试过这个。

您可以像这样使用一些帮助程序并将调用函数作为第一个参数传递 callback

function getDoneTyping (callback, wait = 300) {
  let timer
  const keyDownHandler = event => {
    if (event.key === 'Enter') {
      callback()
    }
    clearTimeout(timer)
  }

  const keyUpHandler = event => {
    clearTimeout(timer)
    timer = setTimeout(callback, wait)
  }
  return { keyDownHandler, keyUpHandler }
}