React 生命週期

何謂 Life Cycle? 中文叫做生命週期,在 React 裡面的組件,當他被產生時、被更新時、被移除時的時間點,透過生命週期函式來完成這些動作,這篇會提到的生命週期函式有:

  1. constructor
  2. render
  3. componentDidMount
  4. componentDidUpdate
  5. componentWillUnmount

constructor

當組件被創時,會先執行 constructor 函式,通常會在裡面做一些初始化的動作,初始化 state、初始化 this 的綁定:

constructor(){
    super()
    this.state = {
        isShow: true
    }
    this.switchText = this.switchText.bind(this)

}

constructor 是組件產生時最一開始執行的起點。

不過因為使用了 create-react-app,Babel plugin 使得這邊不需要做 state 與 Function this 的初始化跟綁定了,總結一
下,在組件產生時,最先執行 constructor。

render

render function 是 React 中最常見到的,因為組件一定要透過渲染的方式,才會把 JSX 結構轉成畫面。

render() {

    const {isShow} = this.state
    return (
        <div>
            {isShow ? <Text/> : null}
            <button onClick={this.switchText}>
                {isShow ? '讓它消失' : '讓它出現'}
            </button>
        </div>
    );
}

將上面兩段程式碼組合起來,可以確定一件事情,組件會先 constructor 後,再進行 render。

componentDidMount

componentDidMount 是在 render 完畫面後,進行的一個函式,可以把一些 非同步函式(像是 Ajax、 setTimeout) 或是 setState 相關的事件放在這裡,請記得不要把 setState 放在 render,因為 render 執行 setState 函式,setState 會使組件重新 render,render 後又會執行 setState,這會是一場很可怕的災難。

嘗試來寫一個 Button 控制一個 Text 組件的存在與否,並在 Title 組件進行 componentDidMount 時執行 setTimeout,兩秒後改變該文字,並且使用 log function 紀錄執行狀況:

class Text extends Component {
    constructor() {
        super()
        this.state = {
            text: 'Hi'
        }
        this.log('constructor');
    }
    componentDidMount(){
        this.log('componentDidMount');
        this.timer = setTimeout(() => {
            this.setState({
                 text: '我是 Title'
            })
        }, 2000);
    }

    log = (lifecycleFuncName) => {
        console.log('Title ' + lifecycleFuncName)
    }

    render() {
        return (
            <div>
                <h2>{this.state.text}</h2>
            </div>
        )
    }

}

class App extends Component {   
    constructor(){
        super()
        this.state = {
            isShow: true
        }
        this.switchText = this.switchText.bind(this)

    }   
    switchText() {
        this.setState({
            isShow: !this.state.isShow
        })
    }

    render() {      
        const {isShow} = this.state
        return (
            <div>
                {isShow ? <Text/> : null}
                <button onClick={this.switchText}>{isShow ? '讓它消失' : '讓它出現'}</button>
            </div>
        );
    }
}

componentDidUpdate

從名字就可以大概知道,當 component 被 update 時,就會觸發:

componentDidUpdate(){
    this.log('componentDidUpdate')
}

將這段加入上面

來試著解讀這段執行順序,先 constructor 再 render,接著執行 componentDidMount,而 setTimeout 的兩秒後會呼叫 setState 改變 Title 組件的 state,剛剛有提到 setState 會使組件重新 render,因此兩秒後重新 render,而組件更新後,也執行了 componentDidUpdate。

但如果按下「讓它消失」按鈕將文字消失,Title 組件消失了,兩秒後的事件還是會做:

這個錯誤是 React 不能對一個 unmount 的組件進行更新,這時候就可以帶到最後一個生命週期函式!

componentWillUnmount

在組件被移除後,有些收拾善後的事情還是要做,就交給 componentWillUnmount 來執行:

componentWillUnmount(){
    this.log('componentWillUnmount')
    clearTimeout(this.timer)
}

也要記錄 log。

可以透過 clearTimeout Function 來解決已經被消去結構的元素進行 unmount。

總結

React 生命週期函式也不只有這五種,也有些不常用的,而可以參考這個連結(上面圖片就是從這來),這系列就到這邊,有錯誤希望大家可以指正,謝謝!

#React







Related Posts

MTR04_0915

MTR04_0915

[Day 02] 工廠模式,策略模式,裝飾者模式

[Day 02] 工廠模式,策略模式,裝飾者模式

Go語言字串

Go語言字串




Sponsored



Comments