這篇要介紹的是 React 元件的生命週期(Life Cycle)。
要認識生命週期的話我們可以先從這個 Life Cycle 圖表網站 瞭解,以下兩張圖是從圖表網站截的圖,上面那張代表整個 Life Cycle 最重要的部分,下面那張則是多呈現一些比較次要的函式。
不過這些圖片出現的函式,大多數都是在 class component 使用,如 componentDidMount、componentDidUpdate、componentWillUnmount...還有非函式的 constructor。functional component 需要透過 react hook 才能擁有類似生命週期的操作。
即使如此,還是可以透過圖片去理解 React 的 Life Cycle,並不會影響太大。
如果你在別人介紹的 Life Cycle 文章看到 componentWillMount、componentWillUpdate 等沒有出現在圖片上的函式,是因為它們已經被廢棄
如圖所示,主要有分成三個階段:
除了這三個階段外,還有 Error handling,做錯誤處理
在 Mounting 的部分,可以看到有五個階段,以下將一一介紹:
這個東西在 class component 使用,主要是在初始化元件的 state 和綁定一些事件,在建立 constructor() 前必須先呼叫 super(props) 這行程式去傳入 props。
範例:
constructor(props) {
super(props);
// Don't call this.setState() here!
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
這個函式是靜態方法(static method),無法操作 class 內的方法&變數。
靜態方法牽涉到物件導向的觀念,就不詳細說明了。
static getDerivedStateFromProps(props, state)
它接受了兩個參數,更新的 props 和當前 state,我們可以使用這個函式讓 props 去修改 state,最後回傳的是一個要更新的 state 物件或是 null,表示不更新 state。
範例:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
render() {
return <Child name="Tom"></Child>;
}
}
class Child extends React.Component{
constructor(props){
super(props);
this.state = { name: "Jean" };
}
static getDerivedStateFromProps(props, state) {
if(props.name !== state.name){
return { name: props.name };
}
return null;
}
render(){
return (
<div> My name is {this.state.name }</div>
)
}
}
export default App;
如程式碼所示,如果 props 的 name 和 state 的 name 不同,就更新 state 的 name 值,若相同就不更新。
另外,在 React 官網介紹 getDerivedStateFromProps()也時有說到有幾種時機不適合使用這個函式:
最後一點是這個函式不太常用到,如果想深入了解以上三個時機推薦閱讀三個你不需要getDerivedStateFromProps的時機 這篇文章,解說的相當詳細。
這個函式一定要在 class component 內撰寫,會回傳以下幾種類型:
class Example extends React.Component {
render() {
return <h1>Hello world!</h1>;
}
}
class Example extends React.Component {
render() {
return <>Hello world!</>;
}
}
class Example extends React.Component {
render() {
return [
<div key="1">Hello</div>,
<div key="2" >World</div>
];
}
}
class Example extends React.Component {
render() {
return "Hello world!";
}
}
class Example extends React.Component {
render() {
return createPortal(this.props.children, document.querySelector("body"));
}
}
要注意的是 render() 這個函式必須是純粹函式,所以不能做一些變更 state 或呼叫 api 等有 side effect 的事情。
當元件呈現在網頁上時就會呼叫這個函式,對應到 React hook 就是 useEffect 會進行呼叫。它用來處理那些有 DOM 元素之後才能做的事,以及更新 state、call api 取得資料。
下篇將會繼續介紹未介紹到的階段。