1五嫂、老的用法
mobx是一個(gè)使用十分普遍的狀態(tài)管理工具房官,在實(shí)際的開(kāi)發(fā)過(guò)程中我們常常搭配react進(jìn)行使用切距。在一些比較大的項(xiàng)目中朽缎,部分變量需要反復(fù)向下層組件進(jìn)行傳遞,如果使用傳統(tǒng)的組件props進(jìn)行實(shí)現(xiàn)谜悟,層層包裹话肖,未免過(guò)于繁瑣,react官方針對(duì)這種場(chǎng)景葡幸,推出了context來(lái)進(jìn)行上下文跨組件傳遞最筒。而mobx也立足于react的context實(shí)現(xiàn)了inject語(yǔ)法,通過(guò)簡(jiǎn)潔的api蔚叨,可以在任何想要使用全局狀態(tài)的地方注入變量床蜘。為了方便進(jìn)行全局的狀態(tài)管理,往往設(shè)定一個(gè)全局的store,其中定義一些全局都會(huì)使用到的變量蔑水,進(jìn)行狀態(tài)控制邢锯,比較典型的例子如下:
import React from 'react';
import { inject, observer } from 'mobx-react';
import comA from 'comA ';
import comB from 'comB';
@inject('globalStore')
@observer
class Test extends React.Component{
render() {
const PanelContent = {
'comA': comA,
'comB': comB
}
const ShowContent = PanelContent[this.props.globalStore.funcType];
return (
<React.Fragment>
<ShowContent />
</React.Fragment>
)
}
}
export default Test ;
這里使用decorator裝飾器語(yǔ)法,通過(guò)字符串的方式注入全局store搀别,組件的this上將會(huì)添加屬性globalStore,通過(guò)store中的funcType的變量來(lái)控制顯示的組件丹擎,該變量變化時(shí),渲染的組件也會(huì)根據(jù)條件變化(通過(guò)observer裝飾器實(shí)現(xiàn))歇父。其外圍容器的寫(xiě)法通常如下:
import React from 'react';
import { Provider, observer } from 'mobx-react';
import Test from 'Text';
import globalStorefrom './globalStore';
class parentCom extends React.Component {
const Store = new globalStore({ funcType: 'comA'});
return (
<Provider globalStore={Store}>
<Test />
</Provider>
)
};
export default parentCom;
其父組件通過(guò)mobx-react的provider包裹器來(lái)將全局的store作為參數(shù)傳入蒂培。哪怕嵌套多層,子組件也可直接通過(guò)添加inject裝飾器來(lái)使用全局store中的變量榜苫,就如Test毁渗。
2、hooks中的inject
react在最新的16.8中啟用了hooks語(yǔ)法单刁,力推函數(shù)式組件灸异,盡管官方表示class式的組件在后續(xù)版本中并不會(huì)廢棄府适,但是hooks是未來(lái)前端框架中組件的發(fā)展方向(最新的Vue也借鑒了react Hook的很多思路),我們需要大膽嘗試新鮮事物肺樟。
到mobx官網(wǎng)上發(fā)現(xiàn)檐春,幾乎所有的例子都是基于class組件來(lái)寫(xiě)的,并沒(méi)有發(fā)現(xiàn)跟react hook搭配使用的內(nèi)容么伯。疟暖。。最后在一個(gè)不起眼處田柔,找到了一個(gè)鏈接俐巴,指向mobx-react的遷移文檔。官方操作如下:
import { MobXProviderContext } from 'mobx-react'
function useStores() {
return React.useContext(MobXProviderContext)
}
自己定義一個(gè)react hook,讓后就可以在我們自己的組件中使用了:
function useUserData() {
const { user, order } = useStores()
return {
username: user.name,
orderId: order.id,
}
}
const UserOrderInfo = observer(() => {
// Do not destructure data!
const data = useUserData()
return (
<div>
{data.username} has order {data.orderId}
</div>
)
})
從官方例子中硬爆,我們可以發(fā)現(xiàn)可以棄用inject語(yǔ)法糖欣舵,直接通過(guò)自定義的useStores,我們就可以實(shí)現(xiàn)獲取外層provider的變量并且使用缀磕,注意此處不能使用解構(gòu)賦值缘圈,否則的話(huà)會(huì)導(dǎo)致無(wú)法實(shí)現(xiàn)變量的觀(guān)測(cè)(即變量改變,頁(yè)面顯示沒(méi)有同步)袜蚕,如果要實(shí)現(xiàn)觀(guān)測(cè):
// use mobx-react@6.1.2 or `mobx-react-lite`
import { useObserver } from 'mobx-react'
function useUserData() {
const { user, order } = useStores()
return useObserver(() => ({
username: user.name,
orderId: order.id,
}))
}
const UserOrderInfo = () => {
// this works now just fine
const { username, orderId } = useUserData()
return (
<div>
{username} has order {orderId}
</div>
)
}
如果你還是想要自己手動(dòng)實(shí)現(xiàn)inject方法糟把,那么官方還給了一個(gè)簡(jiǎn)單的inject組件實(shí)現(xiàn):
import { MobXProviderContext } from 'mobx-react'
function inject(selector, baseComponent) {
const component = ownProps => {
const store = React.useContext(MobXProviderContext)
return useObserver(() => baseComponent(selector({ store, ownProps })))
}
component.displayName = baseComponent.name
return component
}
回到我們自己的組件,如果第一部分中的組件牲剃,要通過(guò)函數(shù)式組件的方式遣疯,使用provider提供的全局store要怎么辦呢?
import React from 'react';
import { observer } from 'mobx-react';
import comA from 'comA ';
import comB from 'comB';
import { useStores } from '@utils/index';
function useStores(name) {
return React.useContext(MobXProviderContext)[name];
}
const Test = () => {
const store = useStores('flagStore'); // 手動(dòng)傳入字符串凿傅,選擇要使用的內(nèi)容
const PanelContent = {
'comA': comA,
'comB': comB
}
const ShowContent = PanelContent[store.funcType];
return (
<React.Fragment>
<ShowContent />
</React.Fragment>
)
}
export default observer(Test );
官方例子中的useStores會(huì)返回所有在context中的內(nèi)容缠犀,也就是所有上級(jí)provider中傳遞的內(nèi)容,此處我們通過(guò)在自己的實(shí)現(xiàn)中傳入一個(gè)字符串來(lái)控制選取我們需要的內(nèi)容狭归。
如有任何疑問(wèn),歡迎留言交流~
————————————————————————————————————
參考文獻(xiàn):
mobx-react遷移官方文檔:
https://mobx-react.js.org/recipes-migration