mobx中的inject,observer遷移至react Hooks寫(xiě)法

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末文判,一起剝皮案震驚了整個(gè)濱河市过椎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戏仓,老刑警劉巖疚宇,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異赏殃,居然都是意外死亡敷待,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)仁热,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)榜揖,“玉大人,你說(shuō)我怎么就攤上這事【儆矗” “怎么了思劳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)妨猩。 經(jīng)常有香客問(wèn)我潜叛,道長(zhǎng),這世上最難降的妖魔是什么壶硅? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任威兜,我火速辦了婚禮,結(jié)果婚禮上庐椒,老公的妹妹穿的比我還像新娘椒舵。我一直安慰自己,他們只是感情好扼睬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布逮栅。 她就那樣靜靜地躺著,像睡著了一般窗宇。 火紅的嫁衣襯著肌膚如雪措伐。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天军俊,我揣著相機(jī)與錄音侥加,去河邊找鬼。 笑死粪躬,一個(gè)胖子當(dāng)著我的面吹牛担败,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镰官,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼提前,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了泳唠?” 一聲冷哼從身側(cè)響起狈网,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎笨腥,沒(méi)想到半個(gè)月后拓哺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脖母,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年士鸥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谆级。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烤礁,死狀恐怖讼积,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸽凶,我是刑警寧澤币砂,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站玻侥,受9級(jí)特大地震影響决摧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凑兰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一掌桩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姑食,春花似錦波岛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至曹鸠,卻和暖如春煌茬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背彻桃。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工坛善, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邻眷。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓眠屎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親肆饶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子改衩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353