---
tags: Note
---
# 基礎 Hook
## useState
useState 關注在狀態的改變
### 寫法
```
const [state, setState] = useState(default)
```
### 說明
- state 代表原狀態,setState 代表改變後狀態,而 useState 後放預設值
- `useState` 會回傳一個包含兩個值的 array,第一個值是 state、第二個值是用來更新 state 的函式,**每當 state 值改變,就會觸發 re-render**,沒改變則不會 re-render。
- 可以宣告多個 state 變數
### 還有這樣的區別
- Pass the state
- 寫法 `setCount(count + 1)`
- 每次都會重新跑(會覆蓋掉上次)
- Pass the function
- 寫法 `setCount(prev => prev + 1)`
- 只跑第一次(不會覆蓋,建議都這樣寫)
---
## useEffect
useEffect 用於非同步請求時
### 寫法
```
useEffect() => { ,[]}
```
### 說明
- 任何會產生 side Effect 的行為都應該 Effect Hook 裡執行
- 跟 `componentDidMount`、`componentDidUpdate`、 `componentWillUnmount` 有著同樣的宗旨,但整合進一個單一的 API
- **after rendering** 才會執行
- `useEffect` 的第二個參數
1. 什麼都不傳:render 後執行
2. 傳空陣列 `[]`:render 後只執行一次
3. 傳有變數的陣列 `[變數]`:render 後這個變數有改變才會執行
#### 副作用 side Effect
官方文件說明,副作用指我們曾在 React component 做過 fetch 資料、訂閱、或手動改變 DOM,這些操作就稱 side effect(簡稱 effect)因為他們可以影響其他 component 且在 render 期間無法完成。
---
## useContext
useContext 讓父子層之間不用手動一層一層傳遞
### 寫法
```
const value = useContext(MyContext);
```
### 說明
- context 中的 `Provider` `consumer` 在 hook、class 中皆可使用
- useContext 的參數必需為 context object 自己
- ` useContext(MyContext)` 只能讀取 context 及訂閱其變更,還是要在 tree 的上層使用 `<MyContext.Provider>` 來提供 context 的值。
---
# 讓寫法優化的 Hook
## useMemo
useMemo 根據改變的值重新計算結果,值沒改變則不觸發狀態改變
### 寫法
```
const check = useMemo(() => {
let sum = 0;
for(let i = 0; i<ocunt*100; i++) {
sum +=1;
}
return sum;
}, [count]);
```
### 說明
- useMemo 再渲染時執行,不是渲染後(與 useEffect 區別),所以不建議做副作用相關操作
- `useMemo` 的第二個參數
1. 什麼都不傳:每次更新就重新計算
2. 傳空陣列 `[]`:只會計算一次
3. 傳有變數的陣列 `[變數]`:這個變數有改變才會重新計算
---
## useCallback
useCallback 是 useMemo 語法糖,能用 useCallback 實現的,都可以用 useMemo
`useCallback(fn, deps)` 相當於 `useMemo(()=>fn,deps)`
### 寫法
```
useCallback(fn, deps) = useMemo(() => fn, deps)
```

### 說明
- 兩者差別,`useMemo` 調用且返回結果,`useCallback` 只返回結果
### 情境
父子組件,子組件接收一個函數做為 props,一般父子組件會一起更新,但有時候子組件沒有更新必要,這時候使用 useCallback 來避免子組件不必要的更新。(借助 useCallback 返回函數,然後把這個函數作為 props 傳給子組件)
---
## useRef
useRef 直接取到指定子層值
### 寫法
```
const refContainer = useRef(initialValue);
```
### 說明
- 類似於類組件 `this.xxx` 寫法
---
## useReducer
useReducer 類似 redux 功能,比起 useState 適合寫更複雜邏輯且含多個子值
### 寫法
```
const [state, dispatch] = useReducer(reducer, initialArg, init);
```
### 說明
- useReducer 的三個參數
1. reduce:類似`(state, action)=> newState` 的函數,傳上一個 state 跟本次的 action
2. state:初始狀態(默認值)
```
const [state, dispatch] = useReducer(
reducer,
{count: initialCount}
);
```
3. 惰性初始化:將計算 state 的邏輯拿到 reducer 外,對之後重置 state 的 action 很方便
- 可以傳遞 dispatch 而不是 callback
---
## useLayoutEffect
useLayoutEffect 裡的 callback 函数在 DOM 更新完成後立即執行,但是在瀏覽器渲染前執行完成,阻塞瀏覽器繪製
> 與 useEffect 結構相同,只是執行時機不同而已
### 說明
- 與 useEffect 不同之處 — 執行時間
- DOM 更新 -> render -> useEffect
- DOM 更新 -> useLayoutEffect -> render
---
## useImperativeHandle
useImperativeHandle 可以讓使用 ref 時能向父 component 暴露自定義的 instance 值
### 寫法
```
useImperativeHandle(ref, createHandle, [deps])
```
---
## useDebugValue
useDebugValue 可以用來在 React DevTools 中顯示自訂義 hook 的標籤
### 寫法
```
useDebugValue(value)
```
### 說明
- 不建議在每個自定義 Hook 都加上 debug 值,它在自定義 Hook 的共享函式庫中才是最有價值的
---
### 自定義 Hook
當我們想重用相同邏輯的組件時,可以自己寫一個 Hook
---
資料來源
- [React Doc](https://zh-hant.reactjs.org/docs/hooks-reference.html)
- [hook 大全](https://blog.csdn.net/qq_41064597/article/details/119175873)
- [hannah hook](https://medium.com/hannah-lin/react-hook-%E7%AD%86%E8%A8%98-%E5%BE%9E%E6%9C%80%E5%9F%BA%E6%9C%AC%E7%9A%84-hook-%E9%96%8B%E5%A7%8B-usestate-useeffect-fee6582d8725)