前提html
在以前項目中,咱們通常是用mobx作數據狀態管理,本文嘗試使用新的方式--react hook,實現狀態管理,比較新舊方式的異同。
本文後面的全部內容的上下文都是在react項目中
歡迎指正,歡迎提出須要補充的地方。
複製代碼
Mobxreact
先對mobx進行簡單介紹,以下圖可見,
從左往右順序查看
1有且僅有action能夠用於修改state,state變化會致使計算屬性(若是有的話)產生變化
2計算屬性的變化會致使reaction被觸發,產生一些反作用,例如更新UI
複製代碼
why Mobxgit
咱們的項目中使用mobx而再也不使用setState緣由有以下幾個(我的理解)
1 setSate 不是同步操做,當咱們經過setstate修改state數據後,後面的邏輯當即取值是舊值,state的新值在下一次render時獲取到。
2 setState 不適合管理全局的狀態。
複製代碼
mobx狀態管理實例github
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.npm
有興趣的同窗能夠康康這個簡單例子
複製代碼
和這個十分鐘入門mobx
複製代碼
使用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的組件更新的數據傳遞
複製代碼
有興趣的同窗能夠看看這個在線demoapp
基於hook擴展的的狀態管理工具 mobx-react-lite
一樣在observable對象內管理狀態,但不使用inject注入store,而是交給context管理
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全局狀態管理