[30DaysChallenge] React LifeCycle 生命週期

30DaysChallenge 是自主性每兩天寫一篇技術相關的部落格

React

Class-based

React 中其實有另一種寫法,class-based

在 Hook 出現以前較常遇見

example from here

class Clock extends React.Component {
  constructor(props) {
    super(props)
    this.state = { date: new Date() }
  }

  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000)
  }

  componentWillUnmount() {
    clearInterval(this.timerID)
  }

  tick() {
    this.setState({
      date: new Date(),
    })
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    )
  }
}

ReactDOM.render(<Clock />, document.getElementById("root"))

而在 16.8 之後出現的 Hook,像是 useState、useEffect 其實與上方的概念的類似,只是名詞不同,使用的地方也不同。

順帶一提,Hook 不能使用在 class-based。

那跟生命週期有甚麼關係呢?


生命週期

生命週期簡單來說就是 React 渲染畫面時,會怎麼執行,可以想像成有一套渲染的 SOP。

透過上圖,可以知道

  • 第一次進入畫面時,先把該弄的資料弄一弄,然後render
  • componentDidMount也就是當元件渲染完成了之後,會執行的其他動作
  • 會依照其他動作,看要不要重新渲染畫面
  • componentDidUpdate當特定的資料改變時,要執行的動作
  • componentWillUnmount也就是當元件從 DOM 消失,要執行的動作

了解這些步驟後,是不是跟某個 hook 很相像呢?

沒錯! 就是 useEffect!

useEffect 的確就是

  • 第一次進入畫面,渲染完後,執行useEffect裡面的動作
  • 爾後,如果useEffectdependencies,也就是填入的資料有被改變時,會再一次進行裡面的動作
  • useEffect中有return Function,將會在消失於DOM/重新執行useEffect之前執行該function

那我們可以說:

useEffect = componentDidMount + componentDidUpdate + componentWillUnmount

應該可以這樣說吧 XD

先前提到的 class-based 的寫法中,useEffect 就會拆分為三種情況,而在 functional 寫法就是一個 useEffect 就可以解決了!


useState?

那 useState 是在 class-based 哪一處對應呢?

constructor(props) {
    super(props)
    this.state = { date: new Date() }
  }

就是這邊啦! this.state

但在 class-based 中,如果要更改狀態的話,我認為 class-based 較為方便,但還是不喜歡

假設有一組資料:

this.state = {
  name: "charlie",
  age: 25,
  gender: "male",
}

透過 this.setState,會幫我們合併新舊資料,這一點與 Hook 的 setState 較為不同

this.setState = {
  name: "john",
  //就不用再把prevState寫出來再合併
}

Class-based or Functional

當然是 Functional (個人最愛?)

  • 不用去想 this 的問題,也不用去想 class or inherit 的問題,看起來比較簡潔(個人覺得),而且 class 是 ES6 才有的語法糖
  • 不過以 class 來說,比較複雜的資料保存、操作反而 class 的寫法就較容易方便
  • 那要拋棄嗎? 由於 Hook 是近年才出現的新東西,class-based 仍然會在許多文件或是專案看見,沒有必要到拋棄,多理解也不會太困難。

08/19,以上有誤再請告知指正>_<