我正在努力应对简单的反跳问题。但是,它以某种方式而不是等待和触发一次,而是等待,而是一个接一个地触发所有事件,直到最后一个事件为止。
它是react组件的一部分。这是代码:
import debounce from "lodash.debounce";
(...)
export default () => {
const { filter, updateFilter } = useContext(AppContext);
const [searchString, setSearchString] = useState(filter.searchString);
const changeFilter = value => {
console.log(value);
};
const changeFilterDebounced = debounce(changeFilter, 3000, true);
const handleChange = e => {
let { value } = e.target;
setSearchString(value);
changeFilterDebounced(value);
};
(...)
因此,如果我在输入中输入类似“ abc”的内容,则会得到
onChange={handleChange}
它稍等片刻(三秒钟),然后将显示三个连续的console.log,其值分别为“ a”,“ ab”,“ abc”。我的期望是使用“ abc”仅触发一次。我想知道我在哪里缺少什么。试图将true作为第三个参数添加,但没有做任何更改,我还创建了一个带有反跳功能的特定函数,而不是每次其他帖子都提到不创建新的反跳。
感谢您的帮助。
答案 0 :(得分:3)
在每次重新渲染时都会重新创建去抖动功能。
您将需要将其包装在useCallback
中,它将保存相同的引用,除非依赖项数组中的变量之一发生更改
const changeFilterDebounced = useCallback(
debounce(value => console.log(value), 3000, true),
[]
)
答案 1 :(得分:0)
在使用功能组件时,所有定义的功能将在每个渲染器上重新初始化,即每次创建一个新的去抖动功能。
可能的解决方法是将useMemo
和useCallback
一起使用,以使函数的引用在每个渲染器上均不变。
const changeFilterDebounced = debounce(changeFilter, 3000, true);
可以更改为:
const changeFilterDebounced = useMemo(() => debounce(changeFilter, 3000, true), [handleChange]);
并用handleChange
将useCallback
包裹起来,例如:
const handleChange = useCallback(e => {
let { value } = e.target;
setSearchString(value);
changeFilterDebounced(value);
}, []);
提供了空的依赖项数组作为useCallback的第二个参数,因此 在组件卸载之前,它的引用将是相同的。
希望这会有所帮助。
答案 2 :(得分:0)
Denounce
很奇怪,因为它基于closure
,可能会导致很多奇怪的事情。 Closure
表示该函数即使返回也可使变量保持活动状态。因此,似乎在调用后有一个实例。
与您的情况一样,您键入了三个字符。每次您键入时,都会调用setState
,该线索会做出反应,从而渲染您的组件并产生一个被谴责的函数。每个被谴责的功能都单独起作用。这就是为什么您得到三个日志的原因。
尝试使用useCallback来确保始终使用第一个被谴责的函数。
答案 3 :(得分:0)
您是否需要将 searchString 设为状态并触发重新渲染?如果没有,您可以只使用 let searchString
并在 handleChange 函数中更新它。我提出了一个要点:https://gist.github.com/mledwards/49fa2c9109d3971871c2f71cced5ff5a