# React 渲染機制 與 生命週期  人有生老病死,元件也有三大生命週期 - Mounting : 元件的 instance 剛開始被建立 ( 一個 instance 只會有一次) - Updating: 元件內部的 props 或 state 被更新的時候 - Unmounting: 元件被移除的時候 而每個生命週期各別的過程當中,又分兩大階段 Render 階段 - 沒有 effect ( 例如修改實際 DOM、呼叫 API ) 這個階段是 react 把「施工藍圖」畫出來,來決定 - 把 **Virtual DOM snapshot** 畫出來,並且和先前的 Virtual DOM snapshot 比較,來決定後續要更新哪些**差異部分**,其中又稱為 diff 計算 - render 的重點在於 : **決定、擬定**哪些內容要實際 render 到 DOM 上 Commit 階段 - 按照 render 階段產生的「施工藍圖」,實際對 DOM 進行操作 ( Mounting & Updating ) ## Hook 時代的 flow 與 cleanup function  在 Class 時期,每個生命週期會有許多對應的 method 來處理,我認為到了 Hooks 時代還是有生命週期,但是每個週期底下 Hooks 已經整合許多過程 其中圖中的 `Effects` 便對應到 `useEffect` 若 component 有設定 `useEffect`,每一次瀏覽器繪製完成後便開始執行 ( 實際是否執行 就要看程式碼內容跟 dependencies array ) 比較容易讓人摸不著頭緒的是 cleanup function,**可以藉由回傳一個函數,來清除上一次的 effect** 為什麼需要 cleanup function ? 如果如果想在 `useEffect` 設立倒數計時,每次 render 完成執行 effect,就開始一個新的 `setTimeout`,如果 render多次**可能會有超多個計時器同時在進行** 所以每次一有新的倒數計時器開始時,需要去清除上一個計時器,這種情況很適合用在 `debouncing` 如果 `useEffect`有 **回傳 cleanup function**,執行的時機點有兩個 : 1. Updating 階段,瀏覽器繪製完畢,**執行上次 effect 回傳的 cleanup function** 2. Unmounting 階段,**執行上次 effect 回傳的 cleanup function** ```jsx const [textValue, setTextValue] = useState(""); useEffect(() => { const id = setTimeout(() => { console.log("Send validation request"); }, 2000); return () => { clearTimeout(id); console.log("clear settimeout"); }; }, [textValue]); ``` 第一次 render 的 effect - 設立一個新的 `setTimeout` 假設 id =1 - 回傳一個 cleanup function 函數,內容是 **「清除 id = 1 的 計時器」** 第二次 render 的 effect - 執行上次 effect 回傳的 cleanup function,**「清除 id = 1 的 計時器」** - 設立一個新的 `setTimeout` 假設 id = 2 - 回傳一個函數,內容是 「清除 id = 2 的 計時器」 ## 實作 debouncing [可以到codesandbox試試看](https://codesandbox.io/s/debouncing-dmupvx?file=/src/App.js:154-454) ## useEffect 大致對應的 Class 生命週期 `useEffect` 透過很巧妙的方式,來類比到 Class 生命週期中的 `componentDidMount`、`componentWillUnmount`和`componentDidUpdate`,因為這三個 method 都是在 render 完畢後執行 但是想要用 `useEffect`完全一模一樣實現這些 Class method,就不太必要了,畢竟 Hook 思維不能和 Class 完全對應 另外 useEffect 的 cleanup function 不像 `componentWillUnmount`只有元件移除的時候才執行 另外,若有 dependencies array,也不能完全類比到 `componentDidUpdate`,因為 dependencies 的情況下,第一次 render 還是會去執行 effect,re-render 的時候才去透過 dependencies 是否改變,來決定是否觸發 useEffect ## Reference https://ithelp.ithome.com.tw/articles/10244959 https://ithelp.ithome.com.tw/articles/10223344
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up