標籤:

MobX vs Redux: Comparing the Opposing Paradigms - React Conf 2017 紀要

毫無疑問,Redux 與 MobX 是 React 生態中最火熱的狀態管理工具,社區也一直沒有停止對上述兩者的討論。近期,團隊小夥伴 @黃子毅 的文章 Mobx 思想的實現原理,及與 Redux 對比,以及正在與我一起翻譯 MobX 中文文檔@岳逢楽 同學的 如果用Redux不爽的話,那就試試MobX吧,都對此發表了自己的觀點。在不久前結束的 React Conf 2017 中,Preethi Kasireddy 也做了相關分享,MobX vs Redux: Comparing the Opposing Paradigms,讓我們來看看她的觀點是怎樣的。

狀態管理上的異同

Redux / MobX 均為客戶端開源狀態管理庫,用狀態來描述 UI 界面,它們與 React 都不具有強綁定關係,你也可以配合別的框架來使用它們。當然,與 React 是再合適不過的了,React 作為 View 層的框架,通過 Virtual DOM 機制來優化 UI 渲染,Redux / MobX 則提供了將相應狀態同步到 React 的機制。

Redux 是 Flux 體系很好的衍生。Flux 具有單向數據流的特點,View 層通過觸發註冊過 dispatcher 的 action,後由 dispatcher 更新相應的 store。同樣 Redux 也具有單向數據流的特點和在 View 層觸發 action,但與 Flux 不同的是,Flux 可以具有多個 store,而 Redux store 是單一數據源。Redux 沒有 dispatcher 的概念,轉而使用純函數(pure function)代替。Redux store 是不可變的(Immutable)。

MobX 類似於 Excel 電子表格,你的數據存放在單元格中,是 observable 的。在 MobX 中具有兩種 derivation,一種是 computed value,它是純函數,相當於 Excel 中的公式,依賴於 observable 數據產生。另一種是 reactions,不同於 computed value 產生新的值,它主要處理副作用(side effect),相當於得到 Excel 公式的結果後,把它們顯示在屏幕上。

Redux 與 MobX 的不同主要集中於以下幾點:

  • Redux 是單一數據源,而 MobX 往往是多個 store。MobX 可以根據應用的 UI、數據或業務邏輯來組織 store,具體如何進行需要你自己進行權衡。
  • Redux store 使用普通的 JavaScript 對象結構,MobX 將常規 JavaScript 對象包裹,賦予 observable 的能力,通過隱式訂閱,自動跟蹤 observable 的變化。MobX 是觀察引用的,在跟蹤函數中(例如:computed value、reactions等等),任何被引用的 observable 的屬性都會被記錄,一旦引用改變,MobX 將作出反應。注意,不在跟蹤函數中的屬性將不會被跟蹤,在非同步中訪問的屬性也不會被跟蹤。
  • Redux 的 state 是只讀的,只能通過將之前的 state 與觸發的 action 結合,產生新的 state,因此是純凈的(pure)。而 MobX 的 state 即可讀又可寫,action 是非必須的,可以直接賦值改變,因此是不純凈的(Impure)。
  • Redux 需要你去規範化你的 state,Immutable 數據使 Reducer 在更新時需要將狀態樹的祖先數據進行複製和更新,新的對象會導致與之 connect 的所有 UI 組件都重複渲染。因此Redux state 不建議進行深層嵌套,或者需要我們在組件中用 shouldComponentUpdate 優化。而 MobX 只自動更新你所關心的,不必擔心嵌套帶來的重渲染問題。
  • 在 Redux 中區分有 smart 組件與 dumb 組件,dumb 負責展示,smart 負責狀態更新,數據獲取。而在 MobX 中無需區分,都是 smart,當組件自身依賴的 observable 發生變化時,會作出響應。

兩者之爭

學習成本上而言,MobX 是常見的 OO 範式,與 Redux 基於函數式的理論相對比不具有新的概念,對於深入傳統面向對象的程序員而言,更為友好。MobX 是 magic 的,通過 computed value、observer class、autorun function 對於 View 層的輸入邏輯進行了抽象,我們只需要在 View 層對相應的 observale 數據進行訪問即可完成自動變更。Redux 儘管源碼簡潔,30 分鐘即可讀完,但一旦開始構建複雜的應用,你就需要開始考慮如何規範化你的 state,如何使用可記憶的 selector 函數(connent 中 mapStateToProps 中對數據的衍生),如何更好地處理非同步等等。

代碼量而言,MobX 由於內置抽象,需要寫的代碼比 Redux 少了很多。對於一個簡單變更狀態的操縱而言,Redux 需要寫 action,在 View 層調用 action,根據相應 action type,寫對應 reducer,MobX 只需要簡單一行即可搞定。

可調試性、可預測性可測試性上而言, Redux 均優於 MobX。Redux 是簡潔、純凈的,能夠進行時間回溯,從 state -> view -> action -> reducer 形成單向閉環,使可調試性和可預測性較好,而對於 action 和 reducer 均可單獨測試。而 MobX 內部較複雜,同時為了代碼的簡潔,可在 View 層直接對 observable 對象進行操作,會使發現問題變得困難。正因如此,MobX 提供了 useStrict 進行限制,只能通過 action 來修改 state。另外 Redux devtool 的完善性和體驗也要好於 MobX devtool。

模塊化的角度來看,MobX 的 store 是分散的,可以用於封裝相應的業務邏輯,Redux 是單一 store,全局共享,沒有所謂的模塊化,最多只是一些拆分。對於你的組件而言,你需要去共享 state 時,單一數據源便是好的。當你的應用複雜後,對於 MobX 分散 store 間的協調、分享數據、相互引用就會很複雜。

可擴展性可維護性方面,Redux 的所有修改會被集中化處理,嚴格按照一個接著一個的順序執行,不需要擔心競態的出現。而 MobX 無法保證嚴格的順序執行,改變可以發生在各個地方,隨著時間的推移,應用可能會出現維護問題。

而在社區方面,Redux 取得完勝。

如何選擇

最初我們是使用 React API setState 來維持組件狀態,但伴隨應用越來越複雜,內部 state 的管理也變隨著複雜,組件間需要共享 state,只能提升到父級。遙遠的葉子節點需要 state,必須從父級逐層傳遞,中間的組件將出現 props 冗餘。這時就需要 Redux / MobX 將組件內部的狀態都抽離出來,做統一管理。

Preethi Kasireddy 認為需要快速開發簡單應用的小團隊可以考慮使用 MobX,因為 MobX 需要開發的代碼量小,學習成本低,上手快,適合於實時系統,儀錶盤,文本編輯器,演示軟體,但不適用於基於事件的系統。

而 Redux 適用於大團隊開發複雜應用,Redux 在可擴展性和可維護性方面可以 hold 住多人協作與業務需求多變,適合商業系統、基於事件的系統以及涉及複雜反應的遊戲場景。

Redux 對 action / event 作出反應,而 MobX 對 state 變化作出反應。在更新邏輯方面,MobX 是在 store 內進行相應封裝,假設一個 UI 操作需要更新多個 store 內的值時,那麼我們需要多次觸發對應 action,或者在多個 store 上再添加一個 store 去進行控制,這都不如 Redux 來得優雅,Redux 只需要觸發一個 action,多個 reducer 可響應相同的 action type,即可完成更新。

最後,Preethi Kasireddy 結合了 Redux 的優勢(純凈的 reducer 與 Immutable store)與 MobX 的優勢(響應式),提出是否有 reducer 與 observable 相結合的可能,很有意思。

後記

在我看來,Redux 崇尚自由,小而美,在框架層面給予了開發者很大的空間,比如可以利用 middleware 機制去抽象業務邏輯。激發了大家造輪子的熱情的同時,也引發了「全家桶」的吐槽,光非同步請求就有 thunk、saga 等多種解決方案,令後來的開發者眼花繚亂。

MobX 則相對封閉,性能優勢與代碼量小,無法掩蓋最佳實踐的缺失。store 應該如何更好地組織?store 間通訊應該如何較好地處理?如何去做一些通用的抽象,比如 store 的復用?都需要我們去一一解決。

正如 Preethi Kasireddy 在演講最後提到的,Redux 或是 MobX 的選擇並不會意味著結束,或者說在現階段下二者都有欠缺。一方面,我們可以通過封裝 Redux 去降低開發成本,來適用自己的業務場景,提高工程效率,比如螞蟻的dva,或是我所在團隊即將開源的框架。亦或我們可以取長補短,MobX 勝在響應式帶來的性能提高,避免不必要的重渲染,如果能與 Redux 的 middleware、reducer 結合,將會非常值得期待。


推薦閱讀:

Mobx 思想的實現原理,及與 Redux 對比
如何評價數據流管理框架 MobX ?
高性能 MobX 模式(part 2)- 響應變化
Mobx 源碼解讀(四) Reaction

TAG:React | MobX | Redux |