【現在學React還來得及嗎:回顧】 
🌳 Evergreen
Recap1 
關鍵字 
- Components:一段可複用的程式碼,React的最小單位。名稱以大寫開頭
 - JSX:類似模板語言的JS語法擴充。會回傳JS物件React element,並最終渲染成DOM。React 17後,JSX將透過jsx-runtime處理
 - Props:Components的參數,可以是任意值。唯讀,只能父傳子
 - Event Handlers:有互動時會觸發的函式。名稱慣例以handle + 元素名稱 + 事件名稱,如handleTitleClick
 - useState:為Components添加狀態。會回傳包含state變數(初始值)和setter(更新前者並觸發渲染)的[ 陣列 ]
 - useImmer:簡化State更新邏輯的第三方Hook。會回傳包含draft(Proxy)和updater(以update開頭)的[ 陣列 ]
 - useReducer:狀態管理用,可透過儲存的State更新介面。useReducer 有兩個參數,分別是Reducer函數和初始State。其中Reducer函數本身包含tasks(初始值)和action(JS物件)兩個參數,會透過事件處理函數dispatch過來的action更新初始State。通常搭配switch…case…
 - useContext:讓Props可以跨組件共享。先創建某某props(createContext),再使用它的值(useContext),後提供(
<Provider>) - 包住傳值對象的
<Provider>標籤,相當於<你創的Props.Provider value={ 你要用的值 }> - useRef:像是沒有setter的useState。不會觸發渲染,但回傳的是具有current屬性,可以修改的
 - useEffect:讓組件可以執行副作用。每次渲染後都會執行,要指定依賴
 - useLayoutEffect:只有執行時機不同於useEffect,執行完程式才重繪畫面
 - useMemo:用來記憶複雜的運算值,避免重新計算以提升效能
 - useCallback:用來記憶函式,避免那個函式因為「跟它無關的變化」重渲染
 
Recap2 
使用時機 
- useState:邏輯簡單時做狀態管理。搭配展開語法、filter、map可分別實作增刪改
 - useReducer:1. 邏輯複雜時做狀態管理(譬如增刪改皆能操作的購物車);2. 當下一個狀態相依於上一個狀態時;3. 更新邏輯想複用於多個組件時
 - useContext:適合做主題切換、讀取帳戶資訊、i18n,亦可做為路由
 - useRef:通常用來操作DOM,或結合useEffect儲存上一個Props/State的值
 - useEffect:當Props/State改變時,會觸發包含在其中的動作(副作用)。通常用來和React之外的系統同步,如非同步請求fetch;有時會拿來寫定時器;依賴值設定成空陣列時,可以處理只有初始化當下的邏輯(相當於onMounted)
 
注意事項 
- Export是具名導出,導入時要搭配大括號,不像默認導出的Default彈性
 - { JS }在JSX中只能作為文本或屬性
 - Props的默認值不能用0或null,和useState、createContext不一樣
 - Setter裡不能寫+=,要使用Immer才能處理mutation
 - 切換布林時要用setState(!state)
 - 如果兩個State總是連動,在State一起更新;如果兩個組件的State總是連動,使用狀態提升;如果兩個邏輯總是連動,可用自訂Hook
 - 不要在State裡用Props
 - 如果UI裡要列出「所選擇元素」,請select ID而非該元素本身
 - key值要標示在父組件裡,因為key值不是全域的
 - 在事件處理函數或Effect裡讀取ref,才不會造成副作用
 - 在組件使用ref屬性只會得到null值,除非使用forwardRef
 - ref和setter不用放進依賴陣列,因為每輪渲染都是相同的
 - 不要把Effect Event傳給其他組件或Hook
 
Recap3 
React vs Vue 
- React要用onChange提供反向資料流,Vue是透過v-model達成雙向綁定
 - Vue的ref類似useState,而非useRef。後者可以保存不用重渲染的資料。
 - Vue的onClick會簡寫成@click,全名是v-on:click
 - useState類似Vue的ref;useRef則是類似Vue的v-model,可拿來取得input的value
 - React styled component可以解決汙染問題,類似Vue style scoped
 - Flow.js可以做型別檢查。由FB開發,很適合搭配React。不過Vue 3也已是全面支援TypeScript
 - 可以拿來做3D的React Three Fiber在2019便發布,而Vue的自定義渲染器TresJS在3年後誕生,比前輩TroisJS還好用
 - React的Class Component有生命週期API,關鍵字是mount, update和 unmount;Functional Component沒有生命週期API,即便useEffect也不是
 - Vue組件的生命週期首先會setup,後續則是對template進行解析。關鍵字比React多了create
 - 在Vue 3的Composition API中,那些生命週期的Hook名稱都以on開頭
 - Jest於三大框架皆可做測試,受React官方推薦;React Testing Library則可用來選取DOM,比Enzyme更以使用者角度思考
 - Vue Test Utils是Vue官方提供用來簡化測試的工具庫,可以用來模擬DOM渲染後的樣貌;基於Vite環境、架構很近似Jest的Vitest才是測試框架;小秘密是:其實也有Vue Testing Library
 
這部分除了拾起、並整理前面文章散落的資訊外,還為了對React有更廣泛的認識,而去填補更多知識、延伸出更多的文字。算是進入實作前的過渡。 查閱資料時發現Vue真的越追越緊,特別是「重新發明Vue」的Vue 3。 接下來很看React 19如何發展了,後生可畏啊。
RSC 
行文至此,鐵人賽已經完成三分之二。雖說有保留約五天的緩衝進度,但每日撰文的壓力對意志仍是考驗。累倒是其次,做這件事占用掉生活多大的比例,又能交換到什麼,才是關鍵。
因此,到了這個階段,我想先來回答一下開篇時所拋出的問題:「現在學React還來得及嗎?」
我會說,不只來得及,還很「著時」。 從React 17開始的功能升級,便替18的改變埋下伏筆。譬如不用遍歷整棵樹,就能使用diff演算法更新部分虛擬DOM的Reconciliation節能版;可以複用Event Object,但因不夠直觀而被取消的Event Pooling機制等。近年來,更是多出不少新觀念。
撇除<Context.Provider>可以寫得更簡潔這種小改款,其中一個在後Hook時代將影響深遠的發展,正是伺服器端組件(React Server Components)。
Takeaway 
- RSC只在伺服器端渲染,檔名為.server.jsx
 - RSC會在伺服器端渲染完;SSR(例如:Next.js)會先在伺服器端預渲染,再hydrate去客戶端
 - 預渲染:使用renderToString(),先渲染HTML過去
 - RSC讓JSX不用在客戶端轉譯
 - RSC和SSR可以同時使用,保留hydrate,相輔相成
 - RSC被視為無狀態的組件,不能用狀態管理的Hook或DOM API
 - RSC讓使用者不用一直透過useEffect獲取資訊
 - RSC將業務邏輯組件化,且不會影響bundle的大小
 - RSC裡可以寫非同步的async和await
 - 客戶端組件不能直接引入RSC,但可以把RSC當成
 - Server Actions:React正在推動,讓客戶端可以更輕鬆調用非同步函式。常見語法有use server、use client等
 - RSC輸出格式:有ID的JSON
 - ID編號有J、M、S、E,分別代表Model、Module、Symbol、Error
 - 其中J是伺服器端渲染的,M是客戶端需要的
 
vDOM 
爬文時常看見「虛擬DOM」一詞,但還沒有梳理過,特於此筆記。
Takeaway 
- 虛擬DOM其實是JS物件
 - Vue也有虛擬DOM,叫作VNode
 - Svelte的哲學是不需要用虛擬DOM
 - 重點不是快慢,而是可以用聲明式語法
 - 好處還有方便維護,以及能做到跨平台使用
 - React18前,由ReactDOM.render()負責將虛擬DOM安插到真實節點
 - React18後,由createRoot和hydrateRoot負責協助
 - 遍歷vDOM tree的時間複雜度是O(n^3),只比對前後差異則是O(n)
 - Fiber透過linked list結構進行遍歷,足以讓虛擬DOM實現增量渲染(Incremental Rendering),可以分割、中斷或調整渲染的優先順序
 - requestIdleCallback():善用零碎時間,讓瀏覽器裡的任務不被單線程耽擱
 - shouldYield():判斷任務執行有沒有超過5毫秒
 - Lanes模型:React 17時引入,關於任務執行的優先順序。相較於16的Expiration Times,可用二進制運算做到更細緻的處理
 - ReactElement的$$typeof屬性是symbol類型,可用來防止XSS攻擊。而倘若瀏覽器不支援symbol類型,React會回傳0xeac7。小彩蛋是因為這串值長得像React,哈
 - lazyTree可以讓IE(8-11)和Edge逐一渲染節點,在遇到特殊節點(例如Fragment)時會進行調整。其他瀏覽器則是都採取一次渲染
 - React 15時是Stack Reconciler加上Renderer,16則是Fiber Reconciler加Renderer再加上 Scheduler。目前則向著Concurrent Features的方向發展中
 
Good Writing 
以下羅列一些寫React的好習慣:
Takeaway 
- 使用Fragments(空標籤)取代無效的div,因其可讀性更高,渲染出的DOM也更小
 - 不會循序改變的state可以使用memo,避免不必要的渲染。不過到React 19情況可能又會有變,因為脫胎自React Forget的React Compiler要來了
 - 在JSX裡使用行內樣式(style={鍵值對}),會比用className外連CSS的效能好,但將沒那麼方便使用media queries和hover等功能。解方如:安裝外掛radium,請自行斟酌。感覺兩邊各有擁護者。另外還有Styled Components、Emotion和Glamorous這樣的CSS-in-JS庫可供參考,更是出現了CSS Modules這樣的模組化解決方案,以亂數解決命名衝突問題。而Next.JS則是採用Styled-JSX
 - 使用強調屬性名稱的物件解構賦值,可讓提取資料更便利,擺脫點記法
 - 不要在JSX裡寫JS
 - 使用更易讀,還可以設定預設值的樣板字面值,取代「加號相連到天邊」的字串串接。這是寫JS時本來就可以保有的反射動作
 - 保持有條理的引入順序:內置 → 外連 → 內連
 - 不要拿會讓人誤會的名稱幫props命名。譬如style或type等可以直接操作DOM的HTML屬性
 - 使用React.lazy動態載入組件,做到程式碼拆分以提升效能
 - 可用PropTypes對props進行型別檢查