为什么我的React反跳处理程序从未调用过?

问题描述

我正在使用React 16.13.0和lodash。建议我使用反跳作为一种在用户键入搜索词时将搜索请求正确发送到服务器的方法。我实现了这个...

...

const handleChange = (event,searchTerm,setSearchTerm,setSearchResults) => {
  console.log("search term:" + searchTerm);
  const query = event.target.value;
  setSearchTerm(query);
  if (!query) {
    setSearchResults( [] );
  } else {
    doSearch(query,setSearchResults);
  }
}

const getDebouncedHandler = (e,handler,delay) => {
  console.log("value:" + e.target.value);
  _.debounce(handler,delay);
}
...

const Search = (props) => {
  const [searchTerm,setSearchTerm] = useState('');
  const [searchResults,setSearchResults] = useState([]);

  const renderSearchResults = ...

  return (
    <div className="searchForm">
      <input
        type="text"
        placeholder="Search"
        value={searchTerm}
        onChange={(e) => {getDebouncedHandler(e,(e) => {handleChange(e,setSearchResults); },100)}}
      />
      {renderSearchResults()}
    </div>
  );
}

export default Search;

问题是,尽管我看到我的“ getDebouncedHandler”方法被调用,但我不认为

_.debounce(handler,delay);

正在做任何事情,因为我从未看到那里列出的方法被调用。我还需要做些什么才能正确调用防抖动处理程序?

编辑:添加用于“ doSearch”的逻辑

const doSearch = (query,setSearchResults) => {
  console.log("before fetch,with query:" + query);
  const searchUrl = "/coops/?contains=" + encodeURIComponent(query);
  fetch(searchUrl,{
    method: "GET",})
    .then((response) => response.json())
    .then((data) => {
      console.log("returning data for " + searchTerm + " query:" + query);
      console.log(data);
      if (query === searchTerm) {
        console.log("setting search results for search term:" + searchTerm);
        setSearchResults(data);
      }
    });
}

解决方法

_.debounce(handler,delay)返回一个函数-您必须将该函数用作事件处理程序。

因此创建一个函数:

const debouncedHandleChange = _.debounce(handleChange,delay)

在jsx中:

onChange = {e => debouncedHandleChange(e,searchTerm,setSearchTerm,setSearchResults)}

您只需要对获取的搜索结果进行反跳操作,而不对输入内容进行反跳操作,即,如果您对设置searchTerm进行反跳操作,则在用户停止输入之前不会设置searchTerm。因此,在他停止键入之前,不会显示他键入的任何内容。因此,请相应地更改代码,看看它是否可以解决您的问题。

,

这里发生了几件事。

  1. lodash.debounce方法返回一个函数。然后必须调用它。
  2. 您传递的事件是综合事件,不会保留以备后用,因此最好尽快传递您需要的内容(event.target.value)。

因此您的代码应如下所示;

import React,{useState} from "react";
import _ from 'lodash';

const handleChange = (value,setSearchResults) => {
  // expect a value here instead of an event
  console.log("search term:" + searchTerm);
  const query = value;
  setSearchTerm(query);
  if (!query) {
    console.log('no search');
  } else {
    console.log('do search');
  }
}

const getDebouncedHandler = (e,handler,delay) => {
  console.log("value : " + e.target.value,handler);
  _.debounce(handler,delay)(e.target.value);
  // 1. call the function
  // 2. pass the function the value you need later
}

const Search = (props) => {
  const [searchTerm,setSearchTerm] = useState('');
  const [searchResults,setSearchResults] = useState([]);
  const renderSearchResults = () => <div>results</div>

  return (
    <div className="searchForm">
      <input
        type="text"
        placeholder="Search"
        value={searchTerm}
        onChange={(e) => {getDebouncedHandler(e,(e) => {handleChange(e,setSearchResults); },100)}}
      />
      {renderSearchResults()}
    </div>
  );
}

export default Search;

这是一个codeandbox链接https://codesandbox.io/s/wonderful-liskov-dj07t?file=/src/App.js:0-1268

为了澄清,我保留了我的答案,以使您的代码保持原样。但这不是正常的模式,您应该使用Ram所指的样式来创建去抖动功能的实例并调用它,而不是在每次击键时都创建一个新的去抖动功能,这并不理想。

,

这是实现此目的的一种方法:

  1. 请勿反跳uniform_real_distribution处理程序,这会导致基本UX,因为某些字符会丢失。
  2. 创建昂贵功能的防反跳版本。通常在这里进行API调用。我认为您的情况是onChange
  3. 如果您使用的是功能组件,请保持已去抖动的功能在组件外部,或者使用doSearch保留引用,否则每次都会创建该引用,并且它不是很有用(它具有内部状态来跟踪上次调用它的时间和其他信息...)。
  4. 请记住,当您调用useMemo时,它将返回一个函数。
  5. 当搜索查询更改时,使用_.debounce来调用去抖动的函数。

代码:

useEffect
,

可能是因为First返回了一个被反跳的函数,所以它不会取消对该函数的调用。

_.debounce

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...