React開發日記-React Hook/Mobx 資料狀態管理對比

YYDev發表於2020-01-13

前提

在之前專案中,我們一般是用mobx做資料狀態管理,本文嘗試使用新的方式--react hook,實現狀態管理,比較新舊方式的異同。
本文後面的所有內容的上下文都是在react專案中

歡迎指正,歡迎提出需要補充的地方。
複製程式碼

Mobx

先對mobx進行簡單介紹,如下圖可見,
從左往右順序檢視
1有且僅有action可以用於修改state,state變化會導致計算屬性(如果有的話)產生變化
2計算屬性的變化會導致reaction被觸發,產生一些副作用,例如更新UI
複製程式碼

React開發日記-React Hook/Mobx 資料狀態管理對比

why Mobx

我們的專案中使用mobx而不再使用setState原因有如下幾個(個人理解)

1 setSate 不是同步操作,當我們通過setstate修改state資料後,後面的邏輯立即取值是舊值,state的新值在下一次render時獲取到。
2 setState 不適合管理全域性的狀態。
複製程式碼

mobx狀態管理例項

mobx的使用方式也很簡單
1 安裝mobx相關的npm
2 宣告一個store類 存放我們需要的資料
複製程式碼
import { action, computed, observable } from "mobx"
class Store {
    // 被觀察者,你可以理解成Vuex中的State,也就是說,宣告一些想要觀察的狀態,變數。
    // 被觀察者可以是:JS基本資料型別、引用型別、普通物件、類例項、陣列和對映
    @observable public num: number = 0;
    
    @computed
    public get addNum() {
        // ...
    }
    
    // 使用@action 更改被觀察者
    @action.bound
    public add() {
        // ...
    }
}
複製程式碼
3 在最頂層使用provider注入所有的store,並且在需要監聽變化的地方的地方使用inject響應的資料,
並在元件宣告之前使用@observerble修飾符將元件改造為觀察者,只要它依賴的任何資料發生變化,就會重新整理元件.
複製程式碼
@inject("store") 
@observer   
class Example extends React.Component<{},{}> {
   public render() {
        return (
            <h1>{this.props.store!.num}</h1>
        )
    }
}
複製程式碼
原理類似於一個使用@computed 宣告的store屬性,使用@observer修飾的元件會自動執行rebuild
複製程式碼

React components are (despite their name) not reactive out of the box. The @observer decorator from the mobx-react package fixes that by wrapping the React component render method in autorun, automatically keeping your components in sync with the state.

有興趣的同學可以康康這個簡單例子
複製程式碼

react中使用mobx的簡單例項-jsfidder開啟

和這個十分鐘入門mobx
複製程式碼

mobx.js.org/getting-sta…

使用react hook 實現全域性狀態管理

1 新建context
複製程式碼
const StateContext = createContext();
複製程式碼
2 設定StateContext.Provider的值為 useReducer
複製程式碼
const StateProvider = ({ reducer, initialState, children }) => (
  <StateContext.Provider value={useReducer(reducer, initialState)}>
    {children}
  </StateContext.Provider>
);
複製程式碼
3 子元件(children) 使用dispath觸發reducer時 導致了Context 的 value的變化
導致了StateContext的value的更新,導致了元件的更新,由此實現 context reducer
->action->state-依賴於State的元件更新的資料傳遞
複製程式碼

有興趣的同學可以看看這個線上demo

codesandbox.io/s/sharp-cor…

基於hook擴充套件的的狀態管理工具 mobx-react-lite

同樣在observable物件內管理狀態,但不使用inject注入store,而是交給context管理

github

react hook狀態管理 在ssr中的問題

主要是從class元件到函式元件的過程中,需要注意的幾個不同點

1 getInitialProps  class的靜態屬性->function元件的屬性
複製程式碼
Page.getInitialProps = async ctx => {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return { stars: json.stargazers_count }
}
複製程式碼
2 原有的class元件中,store可以通過繼承baseStore,在baseStore中,通過傳入initState,
實現CS兩端的狀態同步,而函式元件中,沒有繼承的概念,需要尋找其他方法實現兩端資料同步
複製程式碼

總結

1 使用 context api + useReducer的方式,可以完成大部分狀態管理的需求,適合全域性狀態較為簡單的專案,但尚未解決ssr資料同步問題。

1 mobx 推出了 mobx-react-lite,更新了內部的工作機制,使用context做狀態管理,相對於原先的mobx-react的實現更為輕量(僅支援react 16.8.0+)

原文連結

作者

參考文章

mobx.js.org/getting-sta… 10分鐘入門mobx

juejin.im/post/59df1b… 為什麼我不再使用setstate

juejin.im/post/5d7ba9… react hook全域性狀態管理

React開發日記-React Hook/Mobx 資料狀態管理對比

相關文章