react-best-practices

react-best-practices

在讀取或撰寫 React 元件(.tsx、.jsx 檔案,有 React 匯入)時使用。

51星標
6分支
更新於 2026/6/24
SKILL.md
唯讀
名稱
react-best-practices
描述

在讀取或撰寫 React 元件(.tsx、.jsx 檔案,有 React 匯入)時使用。

React 最佳實務

搭配 TypeScript

使用 React 時,請同時載入此技能與 typescript-best-practices。TypeScript 模式(型別優先開發、差別聯集、Zod 驗證)同樣適用於 React 程式碼。

核心原則:Effect 是逃生門

Effect 讓你「跳出」React 以同步外部系統。大多數元件邏輯不該使用 Effect。 在撰寫 Effect 前,先問:「有沒有不用 Effect 的方法?」

決策樹

  1. 需要回應使用者互動? 使用事件處理器
  2. 需要從 props/state 計算值? 在渲染時計算
  3. 需要快取昂貴的計算? 使用 useMemo
  4. 需要在 prop 變更時重置 state? 使用 key prop
  5. 需要與外部系統同步? 使用 Effect 並清理
  6. 需要在 Effect 中使用非反應式程式碼? 使用 useEffectEvent
  7. 需要不會觸發渲染的可變值? 使用 ref

何時使用 Effect

外部系統同步:瀏覽器 API(WebSocket、IntersectionObserver)、第三方非 React 函式庫、window/document 事件監聽器、非 React DOM 元素(影片、地圖)。

何時不使用 Effect

  • 衍生 state — 在渲染時計算
  • 昂貴的計算 — 使用 useMemo
  • 在 prop 變更時重置 state — 使用 key prop
  • 回應使用者事件 — 使用事件處理器
  • 通知父層 state 變更 — 在同一個事件處理器中更新兩者
  • Effect 鏈 — 在一個事件處理器中計算衍生 state 並更新

Refs

  • 用於不影響渲染的值(計時器 ID、DOM 節點參考)
  • 渲染期間絕不讀取或寫入 ref.current;僅在事件處理器和 Effect 中操作
  • 對於動態列表,使用 ref 回呼(而非在迴圈中使用 useRef
  • 使用 useImperativeHandle 限制父層可存取的內容

自訂 Hook

  • 共享邏輯,而非 state — 每次呼叫都會取得獨立的 state 實例
  • 僅在實際呼叫其他 hook 時才命名為 useXxx;否則使用一般函式
  • 避免生命週期 hook(useMountuseEffectOnce)— 直接使用 useEffect,讓 linter 能捕捉遺漏的相依性
  • 專注於單一具體的使用案例

元件模式

  • 受控:父層擁有 state;非受控:元件擁有 state
  • 偏好使用 children 組合而非 prop 鑽遞
  • 將切換大型元件樹的布林 prop(isEditingisThreadhideAttachments)視為組合的壞味道;針對不同使用案例,偏好使用獨立的組合元件
  • 對於複雜的可重複使用 UI,偏好使用複合元件搭配 provider 範圍的 state/actions,而非帶有許多選擇性 prop 的單一元件
  • 對於範圍內的元件家族以及真正的全域 state,使用 Context,只要它定義了由後代消費的區域介面
  • 直接渲染 JSX 以實現 UI 變化;避免使用設定陣列的迷你框架,除非設定是真正的領域資料
  • 當兄弟或外部控制項需要存取相同的 state/actions 時,提升 provider 邊界
  • 當需要在 state 更新後同步讀取 DOM 時,使用 flushSync

請參閱 react-patterns.md 以取得程式碼範例和詳細模式。