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

如何解决为什么我的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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-