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