React使用useEffect时出现无法对已卸载组件更新状态警告如何解决?
这个警告的触发原因是:你在useEffect中发起的异步请求还未完成时,组件已经被卸载,请求返回后仍然尝试执行state更新操作,才会触发该提示。
你可以通过给useEffect增加清理逻辑的方式解决问题,以下是两种可直接使用的修改方案:
方案1:使用挂载状态标记(适配所有请求封装场景)
仅需修改你现有useEffect部分的代码,不需要调整其他逻辑:
useEffect(() => { // 标记组件是否处于挂载状态 let isMounted = true const user = getUser() getUserById("/user/" + user.userId, user.token) .then((data) => { // 仅在组件仍挂载时更新状态 if (isMounted) { setUserData(data) setLoaded(true) } }) .catch((error) => { if (isMounted) { console.log(error) } }) // 组件卸载时触发的清理函数,修改标记位 return () => { isMounted = false } }, [])
方案2:使用AbortController直接取消请求(更推荐,可节省请求资源)
如果你的getUserById底层是基于fetch/axios实现(几乎所有请求封装都支持),可以用该方案直接在组件卸载时终止未完成的请求:
useEffect(() => { const abortController = new AbortController() const user = getUser() // 注意:需要将signal参数透传给getUserById的底层请求配置 // fetch为例:fetch(url, { signal: abortController.signal, ...其他配置 }) // axios为例:axios.get(url, { signal: abortController.signal, ...其他配置 }) getUserById("/user/" + user.userId, user.token, abortController.signal) .then((data) => { setUserData(data) setLoaded(true) }) .catch((error) => { // 主动取消的请求不需要打印错误日志 if (error.name !== 'AbortError') { console.log(error) } }) // 组件卸载时终止请求 return () => { abortController.abort() } }, [])
以上两种方案任选其一即可解决警告问题。
内容的提问来源于stack exchange,提问作者Pinky Promise
相关产品推荐
相关产品推荐

