本篇主要論述源自於 XState 作者本人在 stackoverflow 的解釋,並輔以一點我的補充。
Redux 比較像作為 state 中央儲存裝置、容器,藉由派發 action 來決定把狀態更新成什麼樣子。
XState 除了作為狀態儲存容器之外,更專注在限制狀態如何才能到下一個狀態 (比如:未繳費 -> 等待出貨),必須限於繳費的事件,需在 Machine config 做出完整的描述
XState 的「狀態( State )」更專注區分主體實際的狀況 或條件 ( condition )以及資料 Data ( context or extended state ) ,以水為例,水的狀態有三種(三態:固、液、氣),而水量是資料可能是 0 到 無限
Redux 的「狀態( State )」則沒被限定,可以是以上兩者其一或混和,可以同時有狀態跟資料,也可以單獨是狀態或資料
Redux 的 Reducer function 可以把它想像成是 一個只要 參數是(state, action)
並且會回傳 state
的任意 function,官方並沒有限制如何實作。
XState 的 Machine Config ,還記得我們之前有自己手刻一個狀態機,其實他可以用雙層的 switch case
實作,他著重在 狀態 + 事件 組成的轉移,可以把 XState 想像成是有更多規則限制的 Reducer function,還另外提供像是階層、平行式狀態、Guard、onEntry、onExit 等。
Redux 官方目前未提供 處理 side effect 內建的方法,必須藉由第三方像是 redux-observable, redux-thunk, redux-saga 等。
XState 內建並提供更細緻的操作方法,讓 side effect 的使用更具描述性(Declarative)、更清晰明確(Explicit),像是 entry: ['notifyActive', 'sendToast'], exit: ['notifyInactive', 'sendToast']
XState 在描述 行為、邏輯是比較明說的,可以輕易將 JSON object config 畫出狀態圖,並從狀態圖看出主體的行為 " onXXX -> target:OOO (onPay -> target:'paid')"
Redux 相較之下在描述行為、邏輯是較為隱晦的,必須去閱讀 swtich / case
返回的夾雜著資料和狀態的 nextState。(不過 Redux 現在也可以透過 JSON object 來描述 reducer 了,可讀性有比較提升)
Redux 官方目前沒有提供工具來視覺化呈現 狀態與狀態 間的轉移;XState 目前有提供,正因為 FSM 具有可描述(Declarative)的特性,使其得以較容易實現。
Redux 必須藉由開發者手動特意排除不可能存在的狀態(比如說:input 元件不可能有 unchanged + invalid 的狀態存在,但卻要靠開發者特意過濾兩個 boolean flag 中無效的邏輯)
XState 因為 StateCharts 需定義 Event 之後要轉移的狀態,自然而然的排除了不可能存在的狀態,而且也比較能在開發前進行靜態規劃跟分析。
在延續新功能、新需求的進入時,只要重新規劃狀態圖的 事件 及 轉移,也避免了 違反 「開放封閉原則」可以見 Day1 和 Day2
Redux 鼓勵將 State 全部中央儲存,在單一 Global 集中控管(雖然我們現在也可以透過 許多 slice, dynamic module 動態載入,但仍集中於一個 store 內)
XState 鼓勵以 Actor Model 的形式,讓 instance 可以各自儲存自己的狀態,但又可以彼此互相溝通(像是之前提到的階層式、父子狀態機 TODO LIST 跟 TODO ITEM 是各自獨立的狀態機,但又能彼此互相溝通)