# React 思維進化
## 5-4~5-5
---
## 觀念回顧
- 對 useEffect 的 dependencies 保持誠實,將依賴資料填入dependencies 陣列中
- useEffect 是用於資料同步化到副作用處理的處理,預設是每次 render 都會自動觸發,而 dependencies 是跳過不必要副作用處理的**效能優化**,i.e. 即使將 dependencies 拿掉,程式碼也會被正確執行
- 如果需要控制執行時機,就透過開發者撰寫**條件式**來符合商業邏輯
---
e.g. 使用 useRef flag 判斷此商業邏輯只有執行一次

---
## [React 18 嚴格模式](https://codesandbox.io/p/sandbox/qr-code-5-3-6-forked-6r86h2?file=%2Fsrc%2FApp.jsx%3A10%2C10)
- 目的:幫助開發者檢查副作用處理是否安全可靠
- 在範例中,Effect function 在 React 18 中在 mount 時被執行兩次
---
- 在 React 的未來版本的規劃中,符合:component 需要被設計得足夠彈性,即使多次 mount 與 unmount 也不會壞掉
- 常用功能 Hot Refresh、未來功能 Offscreen API
- Resuable State 概念
---
### 常用功能 Hot Refresh
React 開發存檔時,會 unmount component,再立刻以新版 component mount 它。過程中 component state 是會被保留不會被清除
### 未來功能 Offscreen API
畫面切換時會保留 component state 與其對應實際 DOM element,直到 component 需要再次顯示時,便可以以之前的 state 狀態再次 mount,以提升效能
---
### Resuable state 概念
- 在 React 未來版本中,當畫面中移除 component 後,仍會可以保留 component state 狀態,以便在需要時可以快速還原並再次 mount
- 生命週期不止 mount 與 unmount 一次
- 即使依賴資料沒有更新,effect function 也可能再次被執行
---
### 目標:「無論重複執行都不多少次都不會壞掉」
- 在嚴格模式中, component 模擬 「mount ⇒ unmount ⇒ mount 行為」。幫助開發者來確保副作用設計的彈性,為 React 未來規劃做好準備
- 因此 component mount 時會有「執行 effect function ⇒ cleanup function ⇒ effect function」的動作
---
透過 React 18 的嚴格模式介紹,讓我們了解 React 的未來規劃中,透過滿足 reusable state 概念達到「副作用處理無論重複執行多少次都不會壞掉」的目標
---
## 觀念檢測
- 為什麼在 React 18 的嚴格模式且為開發環境的版本中,component 的 effect 函式會在 mount 時自動被執行兩次?
- Reusable state 是什麼?
- 為了滿足 reusable state 對於程式碼彈性的要求,我們應該讓副作用處理的設計滿足什麼目標?
---
## 觀念回顧
- 副作用處理理想的效果是造成的影響是可逆的,無論重複執行多少次都不會壞掉
---
## 副作用處理常見的情境設計技巧
### 常見副作用設計問題
1. 疊加性質而非覆蓋性質操作
隨著執行次數變多而不斷疊加時,如果沒有設計 cleanup function 來做取消或逆轉處理,就可能再多次重複執行後造成非預期結果。
---
### 常見副作用設計問題
2. Race condition
多個操作的相對時間順序影響程式存取資源的行為,可能造成不預期結果。e.g. 兩個人同時在同一個網站上修改同一項資料、Fetch Server 端 API 資料回傳順序
---
### 常見副作用設計問題
3. Memory leak
某段程式碼不用了,但記憶體空間尚未被釋放,導致部分記憶體無法被使用。此時除非將整個執行中的應用程式關閉並重新執行,否則記憶體將會被持續佔用。
---
當副作用會啟動持續性的監聽工作,但沒有做對應的取消訂閱就有可能在 component unmount 之後持續監聽,造成效能浪費。e.g. 根據 `props.id` 來訂閱特定訂單的狀態變化監聽(5-1, p. 279-281)

---
一般來說,以上問題都可透過 cleanup function 做適時的處理
---
### 情境 1:Fetch Server 端 API

---

因為前面 fetch 回傳較晚,因此 state 留下的是舊的 data1
---
加上 Flag 判定是否要跳過該次回傳結果

---

---
實務上最推薦使用第三方套件解決 race condition 問題,並內建快取、效能調校等功能。e.g. React Query, SWR, React apollo
---
### 情境 2:控制外部套件
- 新增判斷去確保第三方套件初始化不會被重複執行
- 因為沒有依賴資料,所以可以填空陣列

---
將 React component 內的資料向外部套件進行同步化。每當 state 與前一次不相同時,就會執行同步到 mapmanager

若 zoomLevel 更新頻繁,也可以加入 throttle 優化效能與穩定性,以確保一定時間間隔內只需要執行一次同步到 mapmanager
---
### 情境 3:監聽與訂閱事件
訂閱 DOM 事件、自定義事件,並且需要做取消訂閱,否則該訂閱會在 component unmount 後持續運作,造成 memory leak

---
### 情境 4:使用者觸發事件不該是副作用處理
不應該把「使用者操作行為」處理放在 effect function 中,因為他會隨著 render 被重複執行,即使 cleanup 與無法清除 server 端的 side effect

---
## 觀念檢測
- 我們如何解決副作用設計中「疊加性質而非覆蓋性質的操作」的問題?
- 我們如何解決副作用設計中「rece condition」的問題?
- 我們如何解決副作用設計中「memory leak」的問題?
---
Thank you !
{"title":"React 思維進化","description":"Try HackMD用 HackMD 做簡報HackMD 整合了 reveal.js,讓我們可以用 Markdown 輕鬆寫簡報。讓我們開始吧!","contributors":"[{\"id\":\"f70cb22d-4d8b-4e29-a690-f808410dd689\",\"add\":5053,\"del\":1554}]"}