【问题标题】:Debounce triggering multiple times in react在反应中多次触发去抖动
【发布时间】:2020-03-27 19:41:54
【问题描述】:

我正在努力解决所谓的简单去抖动问题。但不知何故,它不是等待并触发一次,而是等待但触发所有事件,直到最后一个事件。

它是反应组件的一部分。这是代码:

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 作为第三个参数,但没有更改任何内容,而且我还在创建一个具有去抖动功能的特定函数,而不是像其他帖子中提到的那样每次都创建新的去抖动。

感谢您的帮助。

【问题讨论】:

  • 你是如何实现去抖动功能的?
  • @MohammedAshfaq 从 lodash 导入,(已编辑问题)

标签: javascript reactjs lodash debounce


【解决方案1】:

每次重新渲染时都会重新创建去抖动函数。

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

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

【讨论】:

    【解决方案2】:

    当您使用函数式组件时,所有定义的函数都会在每次渲染时重新初始化,即每次都创建一个新的去抖动函数。

    可能的解决方法是同时使用useMemouseCallback,这样函数的引用在每次渲染时都不会改变。

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

    可以改成:

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

    并用useCallback 包裹handleChange,例如:

    const handleChange = useCallback(e => {
        let { value } = e.target;
        setSearchString(value);
        changeFilterDebounced(value);
    }, []);
    

    提供了作为 useCallback 的第二个参数的空依赖数组,所以 在组件卸载之前,它的 ref 将是相同的。

    希望这会有所帮助。

    【讨论】:

    • 也感谢您的回复。与 Asaf Aviv 提出的解决方案相比,将 useMemo 与 useCallback 结合起来有什么优势吗?
    • @Ivo useMemo 用于缓存昂贵的计算,它主要用于存储任何类型的非函数数据。这将增加不必要的开销,因为您只需要保存一个函数。 useMemouseCallback 仍然在每次重新渲染时创建函数,但会被垃圾收集。
    【解决方案3】:

    Debounce 很奇怪,因为它基于closure,这可能会导致许多奇怪的事情。 Closure 表示该函数即使返回,也会使变量保持活动状态。所以调用后好像有实例。

    在您的情况下,您输入了三个字符。每次你输入时,setState 都会被调用,这会导致 react 渲染你的组件并产生一个去抖动的函数。每个去抖函数单独工作。这就是你得到三个日志的原因。

    尝试使用 useCallback 确保您始终使用第一个去抖函数。

    【讨论】:

      【解决方案4】:

      您是否需要 searchString 成为一个状态并触发重新渲染?如果没有,您可以使用 let searchString 并在 handleChange 函数中更新它。我做了一个要点:https://gist.github.com/mledwards/49fa2c9109d3971871c2f71cced5ff5a

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-08
        • 2016-07-03
        • 2019-12-21
        • 2012-12-30
        相关资源
        最近更新 更多