昨天結尾 Context API 的原生缺點,導致寫程式的開發經驗可以再被提升,包含
以上的問題,透過引入 Zustand 使用,可以大幅的解決而使得狀態管理更加簡單跟方便。
簡潔:當你打開一個 Zustand store 時,你應該能夠立即理解它在做什麼,就像閱讀一個簡單的 JavaScript 物件一樣自然。
靈活。可以選擇直接修改狀態,也可以採用不可變更新;可以處理同步操作,也可以輕鬆應對複雜的異步邏輯。
效能導向。每個組件只會訂閱它真正關心的狀態片段,當相關狀態發生變化時才會重新渲染。這種精準的更新機制意味著,即使在擁有數百個組件的大型應用中,狀態變更也能保持高效能的響應速度。
我們想要做一個數數的 component,可以增加、減少 count
這個狀態。
狀態與改變狀態的 function 都直接定義在 store 當中,並可以直接在 React component 呼叫來取得。即便在這個 store 裡頭有別的狀態我們也只會專注在在乎的 state。
隨著應用程式的成長,狀態管理就像城市規劃一樣,需要合理的分區和組織。想像你正在設計一個購物商城的管理系統,你不會把所有功能都塞在一個房間裡,而是會根據功能來劃分不同的區域:用戶服務中心、商品展示區、收銀台、倉庫等等。
如果說基礎的 Zustand store 是一輛性能良好的汽車,那麼中間件就像是為這輛車安裝的各種高科技配件:GPS 導航、自動駕駛系統、安全監控等等。每個中間件都為你的狀態管理系統增加特定的能力。
這個 middleware 解決了網頁應用的一個根本問題:當用戶重新整理頁面或關閉瀏覽器後,應用的狀態會消失。試想把注冊登入的資訊存入了 store,難不成每次刷新頁面或跳轉到分頁,使用者就必須重新登入(這當然是不可能的)
透過 partialize
將特定需要 persist 的狀態存起來。
Immer 解決了深層嵌套狀態更新的痛點。想像你需要修改一個複雜的組織架構圖——在傳統方式下,你需要小心翼翼地複製每一層結構,確保不破壞原有的關係。加上 JS 原生的淺拷貝問題,易與 React immutable 的原則發生衝突,當某個物件作為 hook 的 reference 時,如果拷貝沒有把物件重新賦予,那麼可能導致 UI 沒有被刷新等的非預期行為。
精確訂閱是 Zustand 性能優化的核心概念。想像你正在收聽一個有數百個頻道的廣播電台,如果你只對新聞感興趣,你就不應該同時收聽音樂、體育、娛樂等其他頻道。同樣地,組件應該只訂閱它真正需要的狀態片段。
// 好的做法:只訂閱需要的狀態
const username = useStore(state => state.user.name)
const isLoggedIn = useStore(state => !!state.user)
// 避免的做法:訂閱整個對象
const user = useStore(state => state.user) // 可能造成不必要的重渲染
狀態分割就像是合理規劃房間的使用。你不會把經常使用的物品和很少使用的物品放在同一個抽屜裡。同樣地,經常變化的狀態應該與穩定的狀態分開管理,這樣可以減少不必要的更新。
計算屬性(getter)是 Zustand 中一個被低估的功能。它們就像是智慧助手,能夠根據基礎資料自動計算出衍生資訊,而且只有在依賴的資料改變時才會重新計算。
接下來幾天,將會深入比較 Context vs Zustand vs Redux,以及 Zustand 的更多應用範例。