如何解决为什么我的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。因此,在他停止键入之前,不会显示他键入的任何内容。因此,请相应地更改代码,看看它是否可以解决您的问题。
,这里发生了几件事。
-
lodash.debounce
方法返回一个函数。然后必须调用它。 - 您传递的事件是综合事件,不会保留以备后用,因此最好尽快传递您需要的内容(
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所指的样式来创建去抖动功能的实例并调用它,而不是在每次击键时都创建一个新的去抖动功能,这并不理想。
,这是实现此目的的一种方法:
- 请勿反跳
uniform_real_distribution
处理程序,这会导致基本UX,因为某些字符会丢失。 - 创建昂贵功能的防反跳版本。通常在这里进行API调用。我认为您的情况是
onChange
。 - 如果您使用的是功能组件,请保持已去抖动的功能在组件外部,或者使用
doSearch
保留引用,否则每次都会创建该引用,并且它不是很有用(它具有内部状态来跟踪上次调用它的时间和其他信息...)。 - 请记住,当您调用
useMemo
时,它将返回一个函数。 - 当搜索查询更改时,使用
_.debounce
来调用去抖动的函数。
代码:
useEffect
,
可能是因为First
返回了一个被反跳的函数,所以它不会取消对该函数的调用。
_.debounce
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。