1.译者序React18最近发布后,一些变化对我们使用ReactHooks有一些影响。本文翻译官方文档更新去除“setStateonunmountedcomponentwarning”[1],让大家清楚了解此次变更的背景和影响。这是React18对Hooks的影响系列文章的第一篇,稍后我会整理其他有影响的变化。二、翻译1、背景之前在一个未加载的组件中调用setState时,会有一个警告。这次我们删除了警告。警告内容如下:警告:无法对未安装的组件执行React状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请在useEffectcleanupfunction中取消所有订阅和异步任务。警告:无法在未安装的组件中更改状态。这是无用的操作,它表明您的项目中存在内存泄漏。要解决此问题,请取消useEffect清理函数中的所有订阅和异步任务。不幸的是,这个警告经常被误解和误导。最初是为了确保下面的例子能正常工作:)},[])在这个例子中,如果你忘记在effect清理函数中调用unsubscribe,那肯定是内存泄漏了。2.为什么这个警告具有误导性?其实上面的场景并不常见。相反,以下情况更常见:asyncfunctionhandleSubmit(){setPending(true)awaitpost('/someapi')//componentmightunmountwhilewe'rewaitingsetPending(false)}在上面的代码中,如果请求被发送的组件被卸载时,会抛出一个警告。但是,在这种情况下,该警告具有误导性。这里其实并没有内存泄漏:Promise会很快fulfill,内存会被垃圾回收回收。即使执行没有很快结束,警告也没有用,因为垃圾收集器仍然要等待Promise完成收集,你什么也做不了。一般我们会通过下面的代码来消除警告:handleSubmit(){setPending(true)awaitpost('/someapi')if(!isMountedRef.current){setPending(false)}}其实这种写法是没有用的,并没有解决所谓的“内存泄漏”.它只是抑制警告。前面说了,这里其实并没有内存泄漏。当Promise完成时,内存被释放,没有任何东西可以无限执行。3.上述抑制警告方案比不处理上述抑制警告方案更糟糕,这种方案现在非常非常普遍。但它没有任何好处,比不处理还糟糕:未来,React会提供一个新的能力,当组件卸载不可见时,我们会保存组件的当前状态,但组件仍然会被卸载。下次加载组件时,我们将使用之前保存的状态渲染组件,以恢复之前的页面。组件卸载后,setPending(false)不会执行,所以pending永远为true。那么下次恢复组件的时候,好像请求还没有执行,就会变得更糟。(译者注:关于这块的详细行为和影响,下一篇会介绍)。假设用户点击一个按钮,发起网络请求,请求结束后更新状态。为了避免这种警告,有些人会把请求行为放到useEffect中,因为在useEffect中可以监听组件卸载,从而忽略后续的状态更新,从而消除警告。这段代码变得很不清晰,很糟糕!正是因为这个错误的警告,大家才会写出更糟糕的代码。4.移除警告最后,我们决定移除这个警告。此警告试图解决的订阅问题在日常代码中并不常见。在大多数情况下,它会误导大家并编写更糟糕的代码来避免警告。希望删除此警告将使您能够从代码中删除isMounted。3、译者总结,ahooks中的useUnmountedRef[2]、useSafeState[3]都是为了解决这个warning而生的。同时,在ahooks中必要的地方,为了避免这个报警,我们也会在组件卸载后忽略后续的setState。目前这些代码是冗余的,后续的ahook会陆续优化相关场景,但不会太快。因为这个警告在react16和17中依然存在,会给新手带来不必要的麻烦。我们会等待React18覆盖面更广之后再优化代码。以后你应该不再需要在代码中考虑这个警告,也不需要再使用useUnmountedRef[4]、useSafeState[5]等Hooks。参考[1]更新以删除setStateonunmountedcomponent警告:https://github.com/reactwg/react-18/discussions/82。[2]useUnmountedRef:https://ahooks.js.org/hooks/use-unmounted-ref。[3]使用安全状态:https://ahooks.js.org/hooks/use-safe-state。[4]useUnmountedRef:https://ahooks.js.org/hooks/use-unmounted-ref。[5]使用安全状态:https://ahooks.js.org/hooks/use-safe-state。
