前言
今日前端早读课文章由
KooFE前端团队翻译授权分享。正文从这开始~~
概述严格模式(StrictMode)从React16.3版本开始支持,用于标记出应用中潜在的代码问题。在React应用中添加StrictMode,会对其内部的组件开启一些特殊的行为,并且这些行为只在开发模式下有效。例如,在严格模式下,React会故意加倍渲染组件,以消除不安全的副作用。
随着React18的发布,StrictMode增加了对StrictEffects的支持。在严格模式下,React会对新安装的组件调用两次effect(mount-unmount-mount)。与其他严格模式下的行为一样,React仅在开发环境中执行此操作。
为什么React增加StrictEffects?React的众多功能都会面临着一个约束条件:组件不只一次的挂载(mount)和卸载(unmount)。
FastRefresh就是这些功能中的一个,在Next.js、CreateReactApp和ReactNative中它都默认被开启,每当修改并保持文件时,effect都会被重新执行。这意味着,如果某个组件或库偶尔由于重新运行其effect时出现问题,它将无法很好地使用FastRefresh。
在我们将要支持的功能中同样依赖于这个约束。例如,我们正在开发一种新的OffscreenAPI,它将使我们能够更好地支持UI,如选项卡式容器和虚拟化列表,并更好地使用新的浏览器API,如content-visibility(它还将有助于ReactNative团队正在进行的渲染前优化)。但要达到这一目标,我们需要对effect的工作方式做一些调整。
假设您有一个按条件渲染的组件,例如current选项卡。如果该组件或它的子组件中有一个状态(state),但是当组件一旦被卸载(unmount)这个状态将会立即被丢失。到目前为止,保存状态的唯一方法是将其“提升”到更高的组件(或像Redux这样的外部存储)中。
新的OffscreenAPI(以及本文中描述的effect调整)的主要目的是允许React通过隐藏而不是卸载组件的方式来保持这些状态不会被丢失。在执行此操作时,React将调用与卸载时相同的生命周期hooks,但它还将同时保留React组件和DOM元素的状态。
也就是说,组件可以多次“挂载”和“卸载”。
当一个组件被隐藏时,它无论是在选项卡式容器中还是在虚拟化列表中,它在DOM中不再可见,就像它从DOM中卸载(删除)一样。实际上它并没有被卸载(因为我们希望保留状态),但是从用户的角度来看,它们呈现的效果是相同的。
对于已卸载的组件来说,触发一些命令性代码(例如定位工具提示)是没有意义的。对于隐藏的组件也是如此。所以React需要告诉组件它已经被隐藏。那么如何实现呢?答案是将组件卸载时调用的函数(effect清理函数或