useEffect用於處理副作用的hook,可以在元件渲染後執行額外的操作 **模擬生命週期:** 1. componentDidMount首次元件渲染後會執行useEffect 2. componentDidUpdate當元件狀態更新時,依據dependency判斷來執行useEffect,如有cleanup function會先行執行再執行setup function 3. componentWillUnmount當元件移除時,useEffect會執行cleanup function ## 使用方法 useEffect(setup,[dependencies]) ``` import { useEffect } from 'react'; useEffect(() => {},[]) ``` ### 參數 - setup:要執行的事情。設置函式後還可以使用return返回清除函式 - dependencies:主要用於指定外部某個狀態或變數,dependencies內會當作object.is()來判別是否跟前一次的值有所不同,如果前後比對不同就會再次執行uesEffect。dependencies如果沒有放任何值也可以,但不能連[]都沒有。 object.is()比較後只要是回傳false,就會執行一次useEffect,所以要特別注意放在dependencies內的值,否則會造成無限循環 ``` // Case 1: Evaluation result is the same as using === Object.is(25, 25); // true Object.is("foo", "foo"); // true Object.is("foo", "bar"); // false Object.is(null, null); // true Object.is(undefined, undefined); // true Object.is(window, window); // true Object.is([], []); // false const foo = { a: 1 }; const bar = { a: 1 }; const sameFoo = foo; Object.is(foo, foo); // true Object.is(foo, bar); // false Object.is(foo, sameFoo); // true // Case 2: Signed zero Object.is(0, -0); // false Object.is(+0, -0); // false Object.is(-0, -0); // true // Case 3: NaN Object.is(NaN, 0 / 0); // true Object.is(NaN, Number.NaN); // true ``` ## useEffect執行時機 1. useEffect會在首次元件渲染之後執行 2. 當dependencies有改變時會在元件重新渲染後再次執行,如果dependencies內是空陣列,那麼只會在首次元件渲染後執行一次 3. 當useEffect內有使用到cleanup function時,cleanup function執行時機會在元件移除後執行,或者當元件更新時,會在元件渲染後先執行一次cleanup function後再執行useEffect ``` useEffect(() => { //setup function ... //cleanup function return ... },[]) ``` ## 處理副作用 在使用useEffect與外部系統進行溝通,例如DOM操作或發送API等,這些行為不受React控制都會被稱為外部系統 ### 造成無限循環 在useEffect造成無限循環有: 1. 該狀態會造成重新渲染,導致dependencies改變 2. 沒有設置dependencies <!-- ### 思考修復問題 1. 查看useEffect是否有連接外部系統(DOM、API等)? 2. useEffect為什麼要設置狀態(setState)? 3. 是否與外部系統同步? 4. 是否使用useEffect來管理應用程式的數據流? --> ## cleanup function 使用情境: - 手動設置監聽器的情況下,必須要清除上一次的監聽器,避免造成記憶體溢出 - 拿API的時候,有些需要清除舊的內容 - 需要效能優化時,可以使用cleanup function