React要更新,就像渣男会变心

大家好,我是卡颂。

今天和同事聊天,我说他是个铁憨憨,不会和女生聊天。

他啪的一下跳起来,“我可懂情调了”

“哦?那你来句土味情话。”

他清清嗓子,压低了腔调,望向远方,缓缓道:

  • 如果我是component,我对你的情愫在didMount时燃起,直到我生命unmount时熄灭

正当他沉浸在YY的世界无法自拔时,我说:

  • 你知道在React18,componentDidMount和componentWillUnmount可能调用多次么?

从Strict Mode谈起

React有个特性 — Strict Mode,被StrictMode包裹的组件在DEV环境会对不推荐写法有更严格的提示与辅助检测行为。

 
 
 
 
  1.  
  2.   
     
  3.      
  4.      
  5.   
 
  •  
  • 「辅助检测行为」是指部分方法会被React重复调用,帮助开发者更容易发现不规范使用这些方法时的潜在bug。

    所有会被重复调用的API见StrictMode文档[1]

    举个例子:

     
     
     
     
    1. function App() { 
    2.   const [num, update] = useState(0); 
    3.  
    4.   function onClick() { 
    5.     update(num + 1); 
    6.   } 
    7.  
    8.   console.log('render'); 
    9.  
    10.   return ( 
    11.     {num}

       
    12.   ); 

    当App被StrictMode包裹,点击p触发更新后,App组件会render两次。

    这么做的目的是:作为函数组件,App的「副作用」应该在useEffect回调中执行。

    如果不规范书写副作用(比如在组件函数体内写副作用),那么重复render更容易暴露可能产生的bug。

    铺垫完背景。接下来,让我们揭露React善变的渣男行径。

    最近刷v18讨论组时突然发现:StrictMode中会增加一条Strict Effect规则。

    Strict Effect

    简单的说,类似上文讲到的部分API在StrictMode下会重复执行。

    Strict Effect规则会让useEffect、useLayoutEffect在StrictMode下也会重复执行。

    比如:

     
     
     
     
    1. function App() { 
    2.   // 或useLayoutEffect 
    3.   useEffect(() => { 
    4.     // 逻辑1 
    5.     return () => // 逻辑2; 
    6.   }, []) 
    7.    
    8.   // ... 

    在当前React中,组件mount时,执行逻辑1。

    而在Strict Effect规则下,mount时的逻辑如下:

    注意,这里useEffect的依赖项是[],在以往的认知里,依赖项为「空数组」意味着该useEffect逻辑只会在mount时执行一次。

    而在v18的Strict Mode,由于包含了Strict Effect规则,mount时的useEffect逻辑会被重复执行。

    某种程度上讲,这种打破开发者既有认知的Breaking Change,比Concurrent Mode更让人难以接受。

    那么React团队为什么要设计这条规则呢?

    一切为了Offscreen

    Offscreen是一个开发中的API,预计会在某个v18的小版本发布。

    他的功能类似Vue中的keep-alive,用来在组件「失活」时在后台保存组件状态。

    举个Tab切换的例子,在Posts和Archive之间切换Tab:

    当切换到Posts时,Archive属于「失活」状态。

    如果不需要保存状态,则销毁Archive组件。当切换到Archive Tab时,再重新mount Archive。

    当需要保存状态时,只能将Posts与Archive的状态保存在他们的父组件或状态管理(比如Redux)中。

    而有了Offscreen API,在Fiber树(可以理解为虚拟DOM树)层面,可以保存失活的组件结构与状态。

    这个API的应用场景主要包括:

    现在问题来了:当Offscreen组件从「失活」变为「活动」,会触发什么生命周期函数呢?

    答案是:componentDidMount以及:

     
     
     
     
    1. useEffect(() => { 
    2.    // 触发这个逻辑... 
    3. }, []) 

    当Offscreen组件从「活动」变为「失活」时,会触发componentWillUnmount与:

     
     
     
     
    1. useEffect(() => { 
    2.    // ... 
    3.    return () => { 
    4.      // 触发这个逻辑... 
    5.    } 
    6. }, []) 

    所以,这些曾经被认为在组件生命周期中只会触发一次的方法,由于Offscreen,在未来可能会多次触发。

    这也是React提前在StrictMode中加上Strict Effect规则的原因。

    就像渣男变心前都会有些反常的举动。

    React18是真的挑战

    不管是Offscreen还是Concurrent Mode,可以预见随着v18的到来,React会更强大,相应的学习曲线会更陡峭。

    这既是机遇,也是挑战。

    千万别等变化一股脑到眼前时再埋怨:

    你个渣男,当初说好一心一意只会触发一次,现在为了妖艳新特性,背叛我们的诺言。

    到那时React只会拍拍屁股转身,留下不羁的背影:

    参考资料

    [1]StrictMode文档:

    https://zh-hans.reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects

    标题名称:React要更新,就像渣男会变心
    分享网址:http://www.shufengxianlan.com/qtweb/news1/422401.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    自适应网站知识

    同城分类信息