Day23-React Life Cycle 篇-下篇(Updating & Unmounting & Error handling & Render Phase & Commit Phase)

这篇继续介绍生命周期的另外两个阶段: Updating & Unmounting,以及了解元件在各个生命周期中更新 DOM 的两个阶段 Render Phase & Commit Phase。

Updating

Updating 阶段总共有六个,以下详细介绍:

第一阶段: getDerivedStateFromProps()

请见上篇介绍。

第二阶段: shouldComponentUpdate()

shouldComponentUpdate(newProps, newState) 它接收了两个参数,分别是新的 props 和 state,而这个函式的作用可以从名字就知道,可以用来控制是不是要让元件做更新,可以用它来做效能优化。

这个函式最後回传的是一个 boolean 值,如果是 true 就进入到 render 函式,false 就不会往以下的 life cycle 阶段进行(不会更新元件)
。若没实作 shouldComponentUpdate() 预设会返回 true。

另外还要注意 shouldComponentUpdate() 它在更新 props 和 state 时会呼叫,但如果是透过 forceUpdate() 更新元件就不会呼叫 shouldComponentUpdate()。

第三阶段: render()

请见上篇介绍。

第四阶段: getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate(prevProps, prevState)这个函式在元件实际渲染前被呼叫,接收的两个参数分别是修改前的 props 和 state,用来取得元件 DOM 被修改前的一些资讯。

getSnapshotBeforeUpdate 被执行後的回传值会被传进 componentDidUpdate 的第三个参数。

这个函式不常使用。

第五阶段: 更新 DOM 元素和 Refs

第六阶段: componentDidUpdate()

元件刚刚更新完毕时呼叫,componentDidUpdate(prevProps, prevState, snapshot)总共可以传入三个参数,分别是更新前的 props、state 和 getSnapshotBeforeUpdate 的回传值。

它可以用在元件更新後对应的後续动作,例如比对新props/state 和旧 props/state 的差异,存取 DOM、呼叫 api 等。

若要在 componentDidUpdate() 内去使用 setState,记得要加上条件判断,否则一直更新 state 一直导致元件重新渲染会造成无穷回圈。

Unmounting

最後是元件移除的阶段,不过也就只有一个函式-componentWillUnmount()。

componentWillUnmount()

这个元件作用是将一些用不到的 request、event listeners、setTimeout 移除,等於 useEffect cleanup 的作用。

范例:

componentWillUnmount() {
  clearInterval(this.interval);
}

Error handling

在 React life cycle 里也有内建的错误处理函式,有错误发生时可以使用它们。

getDerivedStateFromError()

static getDerivedStateFromError(error)这个函式为一个静态方法,主要是用来更新 state,让错误画面出现。

记得不能在这里处理 side effect,并且只能回传更新的 state 或 null。

static getDerivedStateFromError(error) {
  return { hasError: true };
}

componentDidCatch()

componentDidCatch(error, info)这个函式可以捕捉从子元件中抛出的错误,并将这个错误讯息提供给 Error Boundary 元件。

这个函式就可以处理 side effect。

Error Boundary

中文可以翻译成"错误边界",这个名词的概念是说如果某个元件发生错误时,包覆该元件的 Error Boundary 元件可以把错误讯息呈现在网页上,并避免影响其它的父元件。

Error Boundary 的限制:

  • 只能捕捉子元件的错误,Error Boundary 元件本身不能捕捉自己
  • 只能捕捉从 constructor(), render() 和各 Lifecycle Methods 中发生的错误
  • Event Handler & 非同步 (Asynchronous) & Server Side Render 程序中发生的错误无法被捕捉

所以还是要用 try catch 来处理无法被 Error Boundary 捕捉的错误。

范例:

<ErrorBoundary>
  <OtherComponent />
</ErrorBoundary>
class ErrorBoundary extends Component {
  state = { errorMessage: null };

  static getDerivedStateFromError(error) {
    // update state
    return { errorMessage: error.message };
  }

  componentDidCatch(error, info) {
    console.log(error, info);
  }

  render() {
    if (this.state.errorMessage) {
      return <h1>{this.state.errorMessage}</h1>;
    }
    return this.props.children;
  }
}

最後介绍的是图片中左侧的 Render Phase、Commit Phase,详细说的话两个阶段中间还有一个 Pre-Commit Phase。

Render Phase

React 在此阶段时会透过 render 函式将 JSX 做转换并生成新的 Virtual DOM ,然後和旧的 Real DOM 做比较(Diff),决定出哪些部分要实际更新到 DOM 元素上。

限制

这个阶段不能有 side effect,并且可以被暂停、中断、重新开始,因此这个阶段包含的建立 constructor、shouldComponentUpdate、render 等函式都必须是纯粹函式。

Pre-Commit Phase

这个阶段发生在 React 要把 React element 加到 DOM 的前一刻,可以读取 DOM。

Commit Phase

将要更新的 Virtual DOM 更新到实际的 DOM 元素,可以进行 side effect 的操作。


参考资料

React lifecycle methods: An approachable tutorial with examples

React 元件生命周期 (Component Lifecycle)

React 错误边界元件

I Want To Know React - Lifecycle 阶段


<<:  [Day22] 发送验证信API – views

>>:  RDS 即时监看

[Day08] 第八章-Laravel的CRUD操作及一些简单指令

前言 今天会介绍laravel一些简单的指令 以及建立路由还有CRUD方法 跟资料库连线喔!! 目标...

成为我们的夥伴,一起航向伟大的航道吧

启航罗~~~ 此篇开始,会介绍AWS上使用完全托管的Kubernetes服务之EKS系列。一般自己托...

参考监视器(Reference monitor)

参考监视器是一概念,而不是实现或系统组件。作为操作系统的关键组件,参考验证机制(即橙皮书中的安全内核...

Day07 - 【入门篇】什麽是OAuth

本系列文之後也会置於个人网站 先来回忆一下,何爲「授权」。试想像有一座宅邸,里头有无数房间。而你作...

不只懂 Vue 语法:请说明 keep-alive 以及 is 属性的作用?

问题回答 <keep-alive> 的作用是缓存一个元件的资料状态,即使它被切换掉,不再...