反跳触发多次反应

时间:2019-12-03 07:01:47

标签: javascript reactjs lodash debounce

我正在努力应对简单的反跳问题。但是,它以某种方式而不是等待和触发一次,而是等待,而是一个接一个地触发所有事件,直到最后一个事件为止。

它是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作为第三个参数添加,但没有做任何更改,我还创建了一个带有反跳功能的特定函数,而不是每次其他帖子都提到不创建新的反跳。

感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

在每次重新渲染时都会重新创建去抖动功能。

您将需要将其包装在useCallback中,它将保存相同的引用,除非依赖项数组中的变量之一发生更改

const changeFilterDebounced = useCallback(
  debounce(value => console.log(value), 3000, true),
  []
)

答案 1 :(得分:0)

在使用功能组件时,所有定义的功能将在每个渲染器上重新初始化,即每次创建一个新的去抖动功能。

可能的解决方法是将useMemouseCallback一起使用,以使函数的引用在每个渲染器上均不变。

const changeFilterDebounced = debounce(changeFilter, 3000, true);

可以更改为:

const changeFilterDebounced = useMemo(() => debounce(changeFilter, 3000, true), [handleChange]);

并用handleChangeuseCallback包裹起来,例如:

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