[英]Pass a argument to a function callback
我正在尝试在 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} />;
}
一开始,我试图在 fetchData function 中使用searchValue
但似乎是因为 scope,它未能读取它,尽管 Z9ED39E2EA931586B6A985A6942EF57EZ 已更新,但它始终为空。
结果,我尝试从debounceLoadData
传递它,但我不知道该怎么做,因为 useCallback 是 function 调用。 如何在fetchData
的debounce
中传递searchValue
。
lodash debounce 将 function 作为第一个参数。 您可以简单地将fetchData
用作 function 并将searchValue
传递给debounceLoadData
,然后在调用时将其传递给fetchData
const debounceLoadData = useCallback(debounce(fetchData, 1000), []);
useEffect(() => {
debounceLoadData(searchValue);
console.log({searchValue})
}, [searchValue]);
debounce 实际上返回一个 function,认为 debounce 是这样实现的
function debounce(func, wait) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait)
}
}
所以基本上debounceLoadData
是这里返回的 function 和arguments passed to it ie..args
然后被传递给原始 function fetch.argsData like func.apply(context, args)
同样debounceLoadData
仅创建一次,因为回调依赖项是[]
,您是否将它作为 not 的依赖项传递给 useEffect 不会有任何区别。
请阅读这篇文章以获取缺少依赖项警告
我从不喜欢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]);
// ...
}
然而,对于您的情况,我不认为使用 lodash debounce 是最好的解决方案。
存在一个隐藏的风险,即在卸载组件之后最终调用效果fetchData
。 如果fetchData
包含一些 state 突变逻辑,则会引发“无法在未安装的组件上调用 setState(或 forceUpdate)”的错误。 这不是破坏性的,但也不是最优的。
我建议使用setTimeout/clearTimeout
手动去抖动调用。 这很简单:
useEffect(() => {
const timeoutId = setTimeout(() => fetchData(searchValue), 1000)
return () => clearTimeout(timeoutId)
}, [searchValue])
我认为您对功能性setState
语法感到困惑。 尝试这个:
const debounceLoadData = useCallback(() => debounce(() => fetchData(searchValue), 1000), []);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.