React中fetch调用后useEffect清理函数的实现方法
解决React中useEffect内fetch请求的清理问题
你遇到的核心问题是:组件卸载后,未完成的fetch请求仍会继续执行,最终调用setImageContainer时会触发已卸载组件的状态更新警告,同时未完成的请求也会浪费资源。用浏览器原生的AbortController就能完美解决这个问题,它可以主动终止fetch请求。
具体实现步骤:
- 创建
AbortController实例,它会生成一个signal信号,用来关联所有需要终止的请求 - 给每个
fetch请求添加signal参数,绑定到这个controller的signal上 - 在useEffect的返回清理函数中调用
controller.abort(),终止所有未完成的请求 - 捕获请求被中止的错误,避免控制台出现不必要的报错
修改后的代码:
const [imageContainer, setImageContainer] = useState([]); const navigate = useNavigate(); useEffect(() => { // 创建AbortController实例 const abortController = new AbortController(); const { signal } = abortController; Promise.all([ fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()), fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()), fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()), fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()), fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()), ]) .then(response => { setImageContainer(response.map(recipe => recipe.meals[0])); }) .catch(error => { // 忽略请求被中止的错误,避免控制台报错 if (error.name !== "AbortError") { console.error("请求出错:", error); } }); // 清理函数:组件卸载时终止所有未完成的请求 return () => abortController.abort(); }, []);
关键说明:
abortController.abort()会触发所有关联该signal的fetch请求立即中止,后续的.then回调不会再执行,自然避免了组件卸载后调用setImageContainer的问题- 捕获
AbortError是因为中止请求会抛出这个错误,它不属于业务错误,所以只在非中止错误时打印日志 - 你的useEffect依赖项是空数组,清理函数只会在组件卸载时执行,完全匹配你的场景
内容的提问来源于stack exchange,提问作者Duka93
相关产品推荐
相关产品推荐

