你們好,我是卡頌。緩存
在咱們React
進階源碼羣裏,除了React
外,狀態管理是最常討論的話題。markdown
詭異的是,有多個羣友說過相似的話:工具
他的同事/組長/領導...讓他把全部state都放在Redux/Mobx...裏性能
他們以爲不對,又不知道如何反駁。單元測試
今天咱們來聊聊Redux
、Mobx
等狀態管理庫和React
、Vue
等視圖庫之間的關係,但願能解決以上困惑。測試
若是你在電梯裏遇到大領導,他問你:spa
小x,大家最近在作什麼功能?code
在電梯到達樓層前這短短2分鐘,你該如何向大領導描述大家正在開發的功能呢?orm
我想你必定會介紹功能的大致邏輯,而不會聊功能裏某個按鈕的具體交互邏輯吧?開發
你會聊邏輯
,而不是交互
。由於邏輯
是最重要的。
接下來咱們經過一個小故事瞭解邏輯
與交互
的關係。
一天,老闆讓你開發文件上傳功能。
開發過程其實就是處理文件上傳這一領域相關的各類狀態之間的關係(好比上傳進度
、是否出錯
...)。
這部分狀態,咱們稱爲領域狀態。
邏輯開發完後,你基於各類領域狀態編寫單元測試。
爲了快速上線驗證該功能是否有人用,你直接將其做爲CLI
工具發佈。
幾天後,通過數據驗證,發現功能很受歡迎。因而你選擇React
做爲視圖庫,基於以前的邏輯開發視圖交互。
開發視圖交互過程當中須要處理視圖相關各類狀態(好比loading顯隱
、打開關閉狀態
...)。
這部分狀態,咱們稱爲視圖狀態。
可見,一款功能完備的產品包含領域狀態與視圖狀態。前者是必須的,後者是可選的。
說回React
、Vue
這樣的視圖庫。
因爲大部分視圖庫以組件做爲模塊邊界,因此很天然的,領域狀態與視圖狀態被分割到不一樣組件中,但他們被分割的方式是徹底不一樣的。
舉個例子,一個完整的應用能夠劃分爲不少組件:
從視圖狀態角度來看這些組件:
對比上下兩張圖,組件1(黃色與綠色)大小一致,表明這是個交互邏輯自洽的純組件(好比一個開關),他的交互邏輯不依賴其餘組件。
除了組件1,更多組件須要與其餘組件造成大小互補,這表明他們的交互邏輯互相影響。
好比組件5的長寬受組件二、組件六、組件8影響,可能表明:組件5是個提示框,他是否彈出受二、六、8影響。
咱們再從領域狀態(藍色部分)角度來看這些組件:
整個應用的邏輯分散在不一樣組件中,可能組件1的didMount
回調中有一部分邏輯,組件3的useEffect
回調中有一部分邏輯。
因爲組件5是個提示框,只有提示效果,因此他不包含應用運轉所必需的邏輯(即領域狀態)。
回到開篇,什麼樣的state
(狀態)應該放在狀態管理裏?
對於視圖狀態:
狀態自洽的組件本身管理狀態(如組件1)
狀態互相之間有影響的組件(如5與二、六、8)根據應用複雜度、組件間跨度決定
若是組件跨度比較近(如是兄弟關係),則公共狀態能夠提高到共同父組件。
若是組件跨度較遠且應用不復雜,能夠提高到共同的Context
中。
若是應用複雜,再考慮狀態管理方案。
對於領域狀態,因爲其天生以碎片形式分佈在不一樣組件中,因此:
簡單的小應用能夠任其分佈在組件中,或者提高到共同的Context
中
其餘狀況推薦用狀態管理方案
甚至,對於領域狀態中的子領域,能夠在有狀態管理方案的基礎上再抽象出來單獨處理。
好比對於服務端請求的數據這一領域狀態,其性質更相似於緩存,在React
中可使用SWR
或React Query
處理。
本文咱們聊了狀態的分類 —— 領域狀態
與視圖狀態
,對於這兩種狀態根據其特性有不一樣處理方案。
雖然一股腦將全部狀態都交給Redux
處理不是不行,但勢必對項目的可讀性、性能、擴展性形成影響。
學完本文可以說服同事/組長/領導最好。若是對方執意要Redux
一把梭,對待這種執(憨)着(憨)的人,牢記四字箴言: