[英]Invalid hook call when trying to fetch data using useCallback
我正在尝试在异步函数中调用useState
例如:
const [searchParams, setSearchParams] = useState({});
const fetchData = () => useCallback(
() => {
if (!isEmpty(searchParams)) {
setIsLoading(true); // this is a state hook
fetchData(searchParams)
.then((ids) => {
setIds(ids); // Setting the id state here
}).catch(() => setIsLoading(false));
}
},
[],
);
我试图在此fetchData
函数( setIsLoading
和setIds
)中设置两种状态,但是每当执行此函数时都会出现错误:
未捕获的错误:无效的挂钩调用。 钩子只能在函数组件的主体内部调用。 这可能是由于以下原因之一而发生的: 1. 你的 React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用
我在这里打破的钩子规则是什么? 有没有办法从函数中设置这些状态?
PS:我在这里只使用了useCallback
钩子来通过lodash/debounce
调用这个函数
编辑:该函数在useEffect
内部useEffect
如:
const debouncedSearch = debounce(fetchSearchData, 1000); // Is this the right way to use debounce? I think this is created every render.
const handleFilter = (filterParams) => {
setSearchParams(filterParams);
};
useEffect(() => {
console.log('effect', searchParams); // {name: 'asd'}
debouncedSearch(searchParams); // Tried without passing arguments here as it is available in state.
// But new searchParams are not showing in the `fetchData`. so had to pass from here.
}, [searchParams]);
您打破的钩子规则关注useCallback
因为您将它作为 fetchData 的结果返回;
useCallback
应该在顶层调用; 不在回调中,像这样:
const fetchData = useCallback(
() => {
if (!isEmpty(searchParams)) {
setIsLoading(true); // this is a state hook
fetchData(searchParams)
.then((ids) => {
setIds(ids); // Setting the id state here
}).catch(() => setIsLoading(false));
}
},
[],
);
你写的代码相当于
const fetchData = () => { return React.useCallback(...
甚至
function fetchData() { return React.useCallback(...
要详细了解为什么不能这样做,我强烈推荐这篇博文。
编辑:
要使用去抖动的searchParams
,您不需要去抖动执行调用的函数,而是去抖动搜索的值。 (你实际上根本没有调用 React.useCallback 的 fetchData 函数,只是直接在你的useEffect
使用它)
我建议使用这个useDebounce
钩子来消除你的搜索查询
const [searchParams, setSearchParams] = React.useState('');
const debouncedSearchParams = useDebounce(searchParams, 300);// let's say you debounce using a delay of 300ms
React.useEffect(() => {
if (!isEmpty(debouncedSearchQuery)) {
setIsLoading(true); // this is a state hook
fetchData(debouncedSearchParams)
.then((ids) => {
setIds(ids); // Setting the id state here
}).catch(() => setIsLoading(false));
}
}, [debouncedSearchParams]); // only call this effect again if the debounced value changes
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.