我在 React 应用程序中使用 lodash debounce 函数,但我似乎无法让它按预期工作。当我尝试对整个函数进行去抖处理时,它可以正常工作,但是当我在另一个函数中调用去抖函数时,会导致对去抖函数的每次调用都运行,而不是仅运行最后一个函数。
这是我的整个功能:
const handleSearchChange = (query: string) => {
setSearchQuery(query)
if (!query.replace(/\W/gi, '')) {
setSearchResults([])
return
}
if (googleAPI) {
fetchGooglePredictions(query)
} else {
fetchMapboxPrediction(query)
}
}
当我对整个函数调用 debounce 时,它会按预期工作。然而,这被称为输入的 onChange,并且对整个事物进行去抖会导致输入更改也去抖。我要做的只是对代码的第二个 if 条件进行反跳,如下:
const getPredictions = (query: string) => {
if (googleAPI) {
fetchGooglePredictions(query)
} else {
fetchMapboxPrediction(query)
}
}
const debounceSearchPredictions = debounce(getPredictions, DEBOUNCE_TIMEOUT)
const handleSearchChange = (query: string) => {
setSearchQuery(query)
if (!query.replace(/\W/gi, '')) {
setSearchResults([])
return
}
debounceSearchPredictions(query)
}
但是现在,getPredictions 的每个调用都会在 DEBOUNCE_TIMEOUT 之后运行,而不仅仅是最后一个调用。以前的人不会提前返回。作为参考, getPredictions 中的两个函数都是异步的;这可能是导致这种行为的原因吗?我也尝试过使用 useCallback 作为 debounce 函数(lodash debounce not debounce in React),但没有运气。
const debounceSearchPredictions = debounce(getPredictions, DEBOUNCE_TIMEOUT)
当您运行此行时,您将创建一个全新的函数。该函数有一个内部计时器,如果多次调用,该计时器将重置。但每次重新运行这行代码时,您都会创建一个不同的函数,并具有自己的独立计时器。因此,您会遇到这样的情况:您不断创建更多函数,每个函数仅被调用一次。
相反,您只需调用
debounce
一次,然后多次调用结果函数。例如:
// Outside the component, so it only happens once
const getPredictions = (query: string) => {
if (googleAPI) {
fetchGooglePredictions(query)
} else {
fetchMapboxPrediction(query)
}
}
const debounceSearchPrediction = debounce(getPredictions, DEBOUNCE_TIMEOUT)
// Inside the component, since it needs to refer to `setSearchQuery`
const handleSearchChange = (query: string) => {
setSearchQuery(query)
if (!query.replace(/\W/gi, '')) {
setSearchResults([])
return
}
debounceSearchPredictions(query)
}
如果你无法将
getPredictions
移到组件之外,因为它依赖于组件内部的某些其他值,那么你可以将其保留在组件内部,但使用 React 的记忆工具仅创建一次:
// Inside the component
const debounceSearchPrediction = useMemo(() => {
const getPredictions = (query: string) => {
if (googleAPI) {
fetchGooglePredictions(query)
} else {
fetchMapboxPrediction(query)
}
}
return debounce(getPredictions, DEBOUNCE_TIMEOUT)
}, []); // <--- add dependencies, if any