英文:
Delaying API calls with debouncing not working in React
问题
我浏览了几篇帖子,但没有找到有用的信息。在一个小的React项目中,显示所有蔬菜图片。它还有一个搜索框,可以获取相关的蔬菜卡片。我正在尝试实现debouncing
函数,但效果不如预期。请查看以下代码。
// useDeounce函数被调用,但不起作用
let newAllData = useCallback(useDebounce(searchData, 1000), []);
const getAllData = async () => {
try {
setLoading(true);
const { data } = await axios.get(
"https://mocki.io/v1/ffbc0f6f-342f-459d-93b4-5921f723b50e"
);
setLoading(false);
setNewData(data);
console.log("NEW DATA", data); // 这在每种文本类型上都被调用
} catch (e) {
setError(e);
console.log(e);
}
};
useEffect(() => {
getAllData();
}, []);
const handleSearch = (value) => {
const event = value;
setSearchData(event);
};
const allData = useMemo(() => {
// 使用debounce的变量-> newAllData 在这里使用
if (!newAllData) return newData;
console.log("NEW DATA HERE", newData);
return (
newData &&
newData?.filter(
(data) =>
(data.name.toLowerCase() && data.name.toLowerCase()).search(
newAllData.toLowerCase()
) !== -1 ||
(data.title.toLowerCase() &&
data.title.toLowerCase().search(newAllData.toLowerCase()) !== -1)
)
);
}, [searchData, newData]);
正如你从上面的代码看到的,getAllData
从API获取数据,并在useEffect
中调用,allData
是一个被记忆的函数,可以防止重新渲染,但是在每一次输入时,API都被调用,因此通过防抖可以减少调用并延迟它。请观察防抖代码。
const useDebounce = (val, delay) => {
const [debValue, setDebValue] = useState(val);
useEffect(() => {
const handler = setTimeout(() => {
setDebValue(val);
}, delay);
return () => {
clearTimeout(handler);
};
}, [val, delay]);
return debValue;
};
适当的解决方案是什么呢?由于这是主要关注点,因为API调用可能会导致性能问题。非常感谢任何建议。
CodeSandbox链接:https://codesandbox.io/s/ecstatic-faraday-j85m9n
英文:
I have gone through several posts but, none useful. So, in a small React project which displays all vegetable images. It also has search box which will fetch relevant vegetable card. I'm trying to implement debouncing
function but, not working as expected. Please follow the code below.
// useDeounce function called but, doesn't work
let newAllData = useCallback(useDebounce(searchData, 1000), []);
const getAllData = async () => {
try {
setLoading(true);
const { data } = await axios.get(
"https://mocki.io/v1/ffbc0f6f-342f-459d-93b4-5921f723b50e"
);
setLoading(false);
setNewData(data);
console.log("NEW DATA", data); // This gets called on every type of text
} catch (e) {
setError(e);
console.log(e);
}
};
useEffect(() => {
getAllData();
}, []);
const handleSearch = (value) => {
const event = value;
setSearchData(event);
};
const allData = useMemo(() => {
// the variable with debounce -> newAllData is used here
if (!newAllData) return newData;
console.log("NEW DATA HERE", newData);
return (
newData &&
newData?.filter(
(data) =>
(data.name.toLowerCase() && data.name.toLowerCase()).search(
newAllData.toLowerCase()
) !== -1 ||
(data.title.toLowerCase() &&
data.title.toLowerCase().search(newAllData.toLowerCase()) !== -1)
)
);
}, [searchData, newData]);
As you can see from above code, getAllData
fetches the data from API and is called in useEffect
, allData
is a memoized function which will prevent it from re-rendering, but, still on every tpye, API is called, hence with debouncing may reduce the calls and delay it. Please observe debouncing code.
const useDebounce = (val, delay) => {
const [debValue, setDebValue] = useState(val);
useEffect(() => {
const handler = setTimeout(() => {
setDebValue(val);
}, delay);
return () => {
clearTimeout(handler);
};
}, [val, delay]);
return debValue;
};
What could be the appropriate solution. Since, this is the major concern as API calls, may cost performance issue. Any suggestion highly appreciated.
CodeSandbox link: https://codesandbox.io/s/ecstatic-faraday-j85m9n
答案1
得分: 1
首先移除包裹你的useDebounce
钩子的useCallback
,这是不必要的。
let newAllData = useDebounce(searchData, 1000);
其次,更新你的useMemo
依赖数组。
const allData = useMemo(() => {
// 使用防抖的变量 -> 这里使用了newAllData
if (!newAllData) return newData;
console.log("NEW DATA HERE", newData);
return (
newData &&
newData?.filter(
(data) =>
(data.name.toLowerCase() && data.name.toLowerCase()).search(
newAllData.toLowerCase()
) !== -1 ||
(data.title.toLowerCase() &&
data.title.toLowerCase().search(newAllData.toLowerCase()) !== -1)
)
);
// 将依赖项从 [searchData, newData] 更改为 [newAllData, newData]
}, [newAllData, newData]);
现在一切应该按预期工作!
英文:
First of all remove the useCallback
that wraps your useDebounce
hook. Thats unnecessary.
let newAllData =useDebounce(searchData, 1000);
Second, update your useMemo
dependency array
const allData = useMemo(() => {
// the variable with debounce -> newAllData is used here
if (!newAllData) return newData;
console.log("NEW DATA HERE", newData);
return (
newData &&
newData?.filter(
(data) =>
(data.name.toLowerCase() && data.name.toLowerCase()).search(
newAllData.toLowerCase()
) !== -1 ||
(data.title.toLowerCase() &&
data.title.toLowerCase().search(newAllData.toLowerCase()) !== -1)
)
);
// Change the dependency here from [searchData, newData] to [newAllData, newData]
}, [newAllData, newData]);
Everything should work now as expected !
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论