iT邦幫忙

2021 iThome 鐵人賽

DAY 22
0
Modern Web

白話JavaScript系列 第 22

Day22-生命週期

前言

這幾天我們已經學習了Props外來傳遞資料,還有State組件本身狀態。

今天要來學習很重要的一個使用觀念 【生命週期】。

而為甚麼我們需要了解所謂的生命週期呢???

這是因為了解組件如何被掛載和被釋放,可以使我們更能夠運用這時間差來達到獲取API或是額外的操作。

今日會學習到的Hooks

  • useEffect
  • useLayoutEffect

Class component

在React官方文檔中有提供我們學習類組件的生命週期
Lifecycle
Lifecycle method

https://ithelp.ithome.com.tw/upload/images/20210919/20130419MGSjWRQ1HY.png

依照組件的掛載與銷毀進度

constructor -> render(回傳JSX)-> componentDidUpdate -> componentWillUnmount -> componentDidMount


useEffect

useEffect是React Hooks中針對生命週期的一個API

syntax

  useEffect(() => {
    // call
  }, [dependency])

若第二個參數為空,即每次只要有組件被更新就會執行

import React,{ useEffect , useState} from 'react'

function App() {
  const [count, setCount] = useState(0)
  useEffect(() => {
   console.log('changed'); 
  })
  return (
    <div></div>
  )
}

export default App

若第二個參數只有[ ] ,則只會執行一次

import React,{ useEffect , useState} from 'react'

function App() {
  const [count, setCount] = useState(0)
  useEffect(() => {
   console.log('changed'); 
  },[])
  return (
    <div></div>
  )
}

export default App

若第二參數我們有指定監控的對象,即該對象更新才會執行

import React,{ useEffect , useState} from 'react'

function App() {
  const [count, setCount] = useState(0)
  useEffect(() => {
   console.log('changed'); 
  },[count])
  return (
    <div>
      <button onClick={() => setCount(count + 1) }>Click</button>
      {count}
    </div>
  )
}

export default App


useLayoutEffect

syntax

  useLayoutEffect(() => {
   // call
  }, [dependency])

你說奇怪為什麼React要用兩個這麼像的API???

以下的code 如果把button按快一點會造成頁面的閃爍

import React,{ useEffect , useState, useLayoutEffect} from 'react'

function App() {
  const [count, setCount] = useState(0)
  useEffect(() => {
   if(count === 0){
     setCount(1)
   }
  },[count])

  return (
    <div>
      <button onClick={() => setCount(0)}>Click</button>
      { count}    
    </div>
  )
}

export default App

如果改成使用useLayoutEffect,就會很順暢並不會閃爍。

import React,{ useEffect , useState, useLayoutEffect} from 'react'

function App() {
  const [count, setCount] = useState(0)
  useLayoutEffect(() => {
   if(count === 0){
     setCount(1)
   }
  },[count])

  return (
    <div>
      <button onClick={() => setCount(0)}>Click</button>
      { count}    
    </div>
  )
}

export default App

為什麼會有以上兩種差別呢???

原因在於當我們使用useEffect狀態快速切換時會造成UI也會快速更新,進而變成畫面跟不上我們點擊的速度。

而如果是使用useLayoutEffect的話,相當於在UI更新前已經先執行好更新狀態,所以狀態提前被準備好。

總結

  • useEffect為非同步函式
  • useLayoutEffect為同步函式

我們看了官方的文檔之後,解釋為同步於DOM更新

https://ithelp.ithome.com.tw/upload/images/20210920/20130419fZWYDVSW1y.png

然而大部分的場景useEffect其實就可以完成我們的工作。


上一篇
Day21-State
下一篇
Day23-資料操作
系列文
白話JavaScript28

尚未有邦友留言

立即登入留言