[英]Pass a argument to a function callback
I'm trying to use debounce in lodash to delay the onChange, see the code below.我正在尝试在 lodash 中使用 debounce 来延迟 onChange,请参见下面的代码。
import React, { useState, useEffect, useCallback } from "react";
import { TopBar } from "@shopify/polaris";
import { debounce } from "lodash";
function SearchBar() {
const [searchValue, setSearchValue] = useState("");
const handleSearchFieldChange = ((value:string) => {
setSearchValue(value);
});
const debounceLoadData = useCallback(debounce({searchValue} => fetchData, 1000), []);
useEffect(() => {
debounceLoadData();
console.log({searchValue})
}, [searchValue]);
function fetchData(value:string) {
console.log("searchValue " + value);
}
const searchFieldMarkup = (
<TopBar.SearchField
onChange={handleSearchFieldChange}
value={searchValue}
placeholder="Search Value"
/>
);
return <TopBar searchField={searchFieldMarkup} />;
}
In the beginning, I was tring to use searchValue
in fetchData function but seems because of scope, it failed to read it, it was always empty though the state had been updated.一开始,我试图在 fetchData function 中使用
searchValue
但似乎是因为 scope,它未能读取它,尽管 Z9ED39E2EA931586B6A985A6942EF57EZ 已更新,但它始终为空。
As a result, I try to pass it in from the debounceLoadData
but I don't know how I can do that as what in useCallback is a function invocation.结果,我尝试从
debounceLoadData
传递它,但我不知道该怎么做,因为 useCallback 是 function 调用。 How can I pass searchValue
in fetchData
inside debounce
.如何在
fetchData
的debounce
中传递searchValue
。
lodash debounce takes in a function as the first argument. lodash debounce 将 function 作为第一个参数。 You can simply use
fetchData
as the function and pass on the searchValue
to debounceLoadData
which will then be passed to fetchData
on invocation您可以简单地将
fetchData
用作 function 并将searchValue
传递给debounceLoadData
,然后在调用时将其传递给fetchData
const debounceLoadData = useCallback(debounce(fetchData, 1000), []);
useEffect(() => {
debounceLoadData(searchValue);
console.log({searchValue})
}, [searchValue]);
debounce actually returns a function, think of debounce as being implemented like debounce 实际上返回一个 function,认为 debounce 是这样实现的
function debounce(func, wait) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait)
}
}
So basically debounceLoadData
is the returned function here and arguments passed to it ie..args
are being then passed to original function fetchData like func.apply(context, args)
所以基本上
debounceLoadData
是这里返回的 function 和arguments passed to it ie..args
然后被传递给原始 function fetch.argsData like func.apply(context, args)
Also debounceLoadData
is created only once as the callback dependency is []
, you whether you pass it to useEffect as a dependency of not will not make any difference.同样
debounceLoadData
仅创建一次,因为回调依赖项是[]
,您是否将它作为 not 的依赖项传递给 useEffect 不会有任何区别。
Please read this post for missing dependency warning请阅读这篇文章以获取缺少依赖项警告
How to fix missing dependency warning when using useEffect React Hook? 使用 useEffect React Hook 时如何修复缺少的依赖警告?
I never like useCallback
, it's quite a confusing hook, and I always use useMemo
instead since it totally covers what useCallback
can do (but not the other way around).我从不喜欢
useCallback
,这是一个非常令人困惑的钩子,我总是使用useMemo
代替,因为它完全涵盖了useCallback
可以做什么(但不是相反)。
function SearchBar() {
const [searchValue, setSearchValue] = useState("");
const handleSearchFieldChange = ((value:string) => {
setSearchValue(value);
});
const debounceLoadData = useMemo(() => debounce(fetchData, 1000), []);
/**
* the equivalent of useCallback should be:
*
* const debounceLoadData = useCallback(debounce(fetchData, 1000), []);
*
* But I really advice against it!
* There's unnecessary function invocation compared to useMemo.
*/
useEffect(() => {
debounceLoadData(searchValue); // <- you should pass in arg
console.log({searchValue})
}, [searchValue]);
// ...
}
Yet for your case I don't think using lodash debounce is the best solution.然而,对于您的情况,我不认为使用 lodash debounce 是最好的解决方案。
There's a hidden risk that the final invocation of effect fetchData
happens AFTER your component is unmounted.存在一个隐藏的风险,即在卸载组件之后最终调用效果
fetchData
。 And if fetchData
contains some state mutation logic, that would raise an error of "Can't call setState (or forceUpdate) on an unmounted component."如果
fetchData
包含一些 state 突变逻辑,则会引发“无法在未安装的组件上调用 setState(或 forceUpdate)”的错误。 which is not destructive but not optimal either.这不是破坏性的,但也不是最优的。
I suggest manually debounce call using setTimeout/clearTimeout
.我建议使用
setTimeout/clearTimeout
手动去抖动调用。 It's pretty simple:这很简单:
useEffect(() => {
const timeoutId = setTimeout(() => fetchData(searchValue), 1000)
return () => clearTimeout(timeoutId)
}, [searchValue])
I think you are getting confused by the functional setState
syntax.我认为您对功能性
setState
语法感到困惑。 Try this:尝试这个:
const debounceLoadData = useCallback(() => debounce(() => fetchData(searchValue), 1000), []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.