Typescript环境下使用React useEffect调用接口时如何避免无限循环
问题核心原因
你的useEffect没有传入第二个参数(依赖数组),这会导致每次组件渲染完成后都会执行该effect代码块。而effect内部执行setDecks更新组件状态后,会触发组件重新渲染,重新渲染又会再次触发useEffect执行,由此形成无限循环。
解决方案
根据你的使用场景选择对应方案即可:
- 如果你只需要在组件首次挂载完成后拉取一次数据做初始化:给
useEffect添加空数组[]作为第二个参数,这样effect仅会在组件首次挂载后执行1次。
修改后的代码如下:React.useEffect(() => { database.getDecks().then((response) => { setDecks(response); }); }, []); // 新增空依赖数组 - 如果你需要在特定变量变化时重新拉取数据:将对应变量添加到依赖数组中,例如需要在用户ID变化时刷新卡组列表,就写成
[userId],此时只有依赖项的值发生变化时,effect才会重新执行。
可选优化:避免内存泄漏
如果组件卸载时请求还未完成,未处理的异步回调可能会引发内存泄漏警告,你可以添加请求取消逻辑:
- 改造
getDecks方法,支持传入AbortSignal:
function getDecks(signal) { return Axious.get(urlGetAllDecks, { signal }).then((response) => response.data); }
- 在
useEffect中添加卸载时的取消逻辑:
React.useEffect(() => { const controller = new AbortController(); database.getDecks(controller.signal) .then((response) => { setDecks(response); }); // 组件卸载时终止请求 return () => controller.abort(); }, []);
内容的提问来源于stack exchange,提问作者oerol
相关产品推荐
相关产品推荐

