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

本文转载自画漫画的程序员

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

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

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

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

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

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

你知道在React18componentDidMountcomponentWillUnmount可能调用多次么?

图片

呵,渣男!

从Strict Mode谈起

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

<StrictMode>
  <div>
    <ComponentOne />
    <ComponentTwo />
  </div>
</StrictMode>

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

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

举个例子:

function App() {
  const [num, update] = useState(0);

  function onClick() {
    update(num + 1);
  }

  console.log('render');

  return (
    <p onClick={onClick}>{num}</p>
  );
}

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

v17之前,例子中console.log会执行两次。但在v17之后,React覆写了console方法,所以console.log只会执行一次,但组件实际会render两次

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

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

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

图片

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

图片

Strict Effect

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

Strict Effect规则会让useEffectuseLayoutEffectStrictMode下也会重复执行。

比如:

function App() {
  // 或useLayoutEffect
  useEffect(() => {
    // 逻辑1
    return () => // 逻辑2;
  }, [])
  
  // ...
}

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

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

  • 组件mount时,执行逻辑1

  • React模拟组件unmount,执行逻辑2

  • React模拟组件mount,执行逻辑1

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

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

图片

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

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

一切为了Offscreen

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

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

举个Tab切换的例子,在PostsArchive之间切换Tab

图片

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

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

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

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

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

  • 切换路由时保存之前路由的状态

  • 预加载将要切换的路由

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

答案是:componentDidMount以及:

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

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

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

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

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

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

图片

React18是真的挑战

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

这既是机遇,也是挑战。

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

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

图片

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

图片

  • 24
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
为了熟练掌握 React 技术栈,你需要掌握以下几个关键技术: 1. ReactReact 是一个用于构建用户界面的 JavaScript 库,它提供了组件化的开发模式,使得构建复杂的 UI 更加简单和可维护。 2. JSX:JSX 是一种 JavaScript 的语法扩展,它允许你在 JavaScript 中编写类似 HTML 的代码。在 React 中,你会经常使用 JSX 来描述 UI 的结构。 3. 组件:组件是 React 开发中的基本单位,每个组件可以独立管理自己的状态和 UI。通过组件化的开发模式,你可以将复杂的 UI 分解为更小、可复用的部分。 4. State 和 Props:State 是组件内部的状态,可以通过 setState() 方法进行更新。Props 是从父组件传递给子组件的数据,它们是只读的。 5. 生命周期:React 组件有不同的生命周期阶段,比如组件的创建、更新和销毁等。了解这些生命周期方法可以帮助你在合适的时机执行逻辑代码。 6. 虚拟 DOM:React 使用虚拟 DOM 来跟踪页面上的变化,并高效地更新实际 DOM。了解虚拟 DOM 的工作原理可以帮助你编写更高效的代码。 7. 状态管理:对于大型应用程序,你可能需要使用状态管理库来管理组件之间的共享状态。Redux 和 MobX 是两个常用的状态管理库。 8. 路由:React Router 是一个常用的路由库,它可以帮助你在 React 应用中实现页面的导航和路由功能。 除了以上技术,还有其他相关的工具和库,比如 Webpack、Babel、Axios 等。熟练掌握这些技术和工具可以帮助你构建出更好的 React 应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值