大家好,我是Kason。今天和同事聊天,我说他是个硬汉,不会和女生聊天。他猛地跳了起来,“我能理解情绪。”“哦?那你有一段土气的爱情故事。”他清了清嗓子,放低语气,望着远方,缓缓说道:如果我是一个组件,我会在挂载时点燃你的情意,在挂载时点燃我的生命。正当他沉浸在YY的世界里无法自拔时,我说:你知道在React18中,componentDidMount和componentWillUnmount可能会被调用多次吗?从StrictMode说起React的一个特性——StrictMode,被StrictMode包裹的组件对于DEV环境下不推荐的写法会有更严格的提示和辅助检测行为。
“辅助检测行为”是指一些方法会被React重复调用,帮助开发者更容易发现这些方法何时被调用没有标准化。潜在的错误。所有会被重复调用的API,参见StrictMode文档[1]例如:functionApp(){const[num,update]=useState(0);functiononClick(){update(num+1);}console.log('使成为');return({num}
);}当App被StrictMode包裹后点击p触发更新,App组件会渲染两次。在v17之前,示例中会执行两次console.log。但是在v17之后,React重写了console方法,所以console.log只会执行一次,但组件实际上会渲染两次。这样做的目的是:作为一个函数组件,App的“副作用”应该在useEffect回调中执行。如果副作用没有以标准化的方式编写(例如在组件函数体中编写副作用),重复渲染更容易暴露可能的错误。完成背景。接下来,让我们揭露React善变的行为。最近浏览v18讨论组的时候,突然发现StrictMode中会增加一个StrictEffect规则。StrictEffect简单的说就是在StrictMode下会重复执行一些类似于上面提到的API。StrictEffect规则会导致useEffect和useLayoutEffect在StrictMode中重复执行。例如:functionApp(){//或useLayoutEffectuseEffect(()=>{//logic1return()=>//logic2;},[])//...}在当前的React中,当组件挂载,执行逻辑1,在StrictEffect规则下,挂载逻辑如下:组件挂载时,执行逻辑1卸载React模拟组件,执行逻辑2挂载React模拟组件,执行logic1注意这里useEffect的依赖是[],在以往的认知中,依赖是“空数组”意味着useEffect逻辑在mount的时候只会执行一次。在v18的StrictMode中,由于包含了StrictEffect规则,所以mount时的useEffect逻辑会被反复执行。从某种程度上来说,这种打破开发者既有认知的BreakingChange,比ConcurrentMode更让人难以接受。那么React团队为什么要设计这个规则呢?AllforOffscreenOffscreen是一个开发中的API,预计将在v18的小版本中发布。它的作用类似于Vue中的keep-alive,用于在组件“去激活”时在后台保存组件状态。举个Tab切换的例子,在Posts和Archive之间切换Tab:当切换到Posts时,Archive处于“停用”状态。如果不需要保存状态,则销毁Archive组件。切换到ArchiveTab时,再次挂载Archive。当需要保存状态时,只能在其父组件或状态管理(如Redux)中保存Posts和Archive的状态。通过OffscreenAPI,可以将不活动的组件结构和状态保存在Fiber树级别(可以理解为虚拟DOM树)。该API的应用场景主要包括:切换路由时,保存上一条路由的状态,并预加载要切换的路由。现在问题来了:当Offscreen组件从“deactivated”变为“active”时,会触发什么生命周期函数?回答是:componentDidMountand:useEffect(()=>{//Triggerthislogic...},[])当Offscreen组件从“active”变为“deactivated”时,会触发componentWillUnmountand:useEffect(()=>{//...return()=>{//Triggerthislogic...}},[])因此,这些曾经被认为在组件生命周期内只触发一次的方法,由于Offscreen,将来可能会被多次触发。这也是为什么React会提前在StrictMode中加入StrictEffect规则。就像一个伤心欲绝的人在他改变主意之前会表现异常。React18是一个真正的挑战。无论是Offscreen还是ConcurrentMode,可以预见随着v18的到来,React会更加强大,相应的学习曲线也会更加陡峭。这既是机遇也是挑战。别等变化全在脑子里抱怨了:你个没良心的人,你说一心只触发一次,现在却背叛了我们对新功能的承诺。到时候React只会拍拍屁股转身,留下一个不羁的背影:参考[1]StrictMode文档:https://zh-hans.reactjs.org/docs/strict-mode.html#detecting-unexpected-副作用