在反应中多次触发去抖动
Debounce triggering multiple times in 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 作为第三个参数,但没有改变任何东西,我还创建了一个带有去抖动的特定函数,而不是像其他帖子中提到的那样每次都创建一个新的去抖动。
感谢您的帮助。
每次重新渲染时都会重新创建去抖功能。
您需要将其包装在 useCallback
中,它将保持相同的引用,除非依赖项数组中的变量之一发生变化
const changeFilterDebounced = useCallback(
debounce(value => console.log(value), 3000, true),
[]
)
当您使用功能组件时,所有定义的功能都将在每次渲染时重新初始化,即每次都创建一个新的去抖功能。
可能的解决方法是同时使用 useMemo
和 useCallback
,这样每次渲染时函数的引用都不会改变。
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的第二个参数,所以
在组件卸载之前它的引用将是相同的。
希望对您有所帮助。
Debounce
很奇怪,因为它基于 closure
,这可能会导致许多奇怪的事情。 Closure
表示即使 returns 函数仍保持变量活动。所以调用后好像有一个实例
与您的情况一样,您键入了三个字符。每次您键入时,都会调用 setState
,这会导致反应呈现您的组件并产生去抖功能。每个去抖函数都是单独工作的。这就是你得到三个日志的原因。
尝试使用 useCallback 以确保您始终使用第一个去抖功能。
我正在努力解决所谓的简单去抖动问题。但是不知何故,它不是等待并触发一次,而是等待但一个接一个地触发所有事件,直到最后一个。
它是反应组件的一部分。这是代码:
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 作为第三个参数,但没有改变任何东西,我还创建了一个带有去抖动的特定函数,而不是像其他帖子中提到的那样每次都创建一个新的去抖动。
感谢您的帮助。
每次重新渲染时都会重新创建去抖功能。
您需要将其包装在 useCallback
中,它将保持相同的引用,除非依赖项数组中的变量之一发生变化
const changeFilterDebounced = useCallback(
debounce(value => console.log(value), 3000, true),
[]
)
当您使用功能组件时,所有定义的功能都将在每次渲染时重新初始化,即每次都创建一个新的去抖功能。
可能的解决方法是同时使用 useMemo
和 useCallback
,这样每次渲染时函数的引用都不会改变。
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的第二个参数,所以 在组件卸载之前它的引用将是相同的。
希望对您有所帮助。
Debounce
很奇怪,因为它基于 closure
,这可能会导致许多奇怪的事情。 Closure
表示即使 returns 函数仍保持变量活动。所以调用后好像有一个实例
与您的情况一样,您键入了三个字符。每次您键入时,都会调用 setState
,这会导致反应呈现您的组件并产生去抖功能。每个去抖函数都是单独工作的。这就是你得到三个日志的原因。
尝试使用 useCallback 以确保您始终使用第一个去抖功能。