虽然我无法准确地告诉您何时调用useEffect
的unsubscribe函数比"卸载组件时"更具体,但我can回答了您关于何时调用它的含义的问题:
是否有可能在组件卸载和调用清理之间解决promise ,从而导致错误,即访问已解除分配的状态?
在编写的代码中,promise 可以解决after个组件的卸载问题.您的isApiSubscribed
标志是一种隐藏在开发模式中发生这种情况时可能显示的警告的方法,但它是not the correct way of dealing with this scenario.
当react在开发模式下运行时发生这种情况,您可能会收到如下警告消息:
警告:无法对已卸载的组件执行react 状态更新.这是一个no-op,但它表示应用程序中存在内存泄漏.要修复此问题,请取消componentWillUnmount方法中的所有订阅和异步任务.
此警告消息的要点是,在卸载特定组件后,应小心停止执行不再相关的工作.不调用setData
会阻止您更新状态,但HTTP请求的工作仍将始终完成,即使组件已卸载.That'sreact 是告诉你应该考虑取消.
改变此模式以避免花费不必要资源的"正确"方法是在组件卸载时停止HTTP请求的执行,这将导致promise 拒绝:
useEffect(() => {
const abortController = new AbortController();
axios.get(API, { signal: abortController.signal }).then((res) => {
setData(res.data)
});
return () => {
abortController.abort();
};
}, []);
这不仅确保了您不会对已卸载的组件调用setData
(这是一项相对琐碎的工作),而且还确保了在卸载组件时取消更大的工作,即HTTP请求(以及相关的响应处理).
从理论上讲,可能会发生以下一系列事件:
- 任务开始
- 任务完成
- promise 解决
- 组件卸载
- 触发下一个事件tick,并调用传递给then()的continuation,调用setData(),触发警告消息
但这需要精确的时间,警告信息的精神是防止更常见的情况:
- 任务开始
- 组件卸载
- 任务完成
- promise 解决
- 下一个事件勾号触发器