1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Custom Hooks 中使用 React Context

        共 3336字,需瀏覽 7分鐘

         ·

        2021-10-11 09:05

        在上一篇 對于 Custom React Hooks 一些思考 文章末尾提及了 React Context,那么在本篇中我們將了解一下 React Context 怎么解決狀態(tài)共享問題以及一些其它想法。

        關(guān)于 React Context

        提供 官網(wǎng)對于 ?usecontext 的介紹

        const?value?=?useContext(MyContext);

        無論組件在組件樹中的深度如何,React Context 都為組件提供數(shù)據(jù)。上下文用于管理全局?jǐn)?shù)據(jù),例如 全局狀態(tài)、主題、服務(wù)、用戶設(shè)置等。

        那么我們回到上篇文章提及到的例子吧,如何在父子組件中共享 useBoolean 返回的狀態(tài)呢?

        怎樣使用 Context

        在給出一份解決方案前,先來說明一下如何使用 Context。步驟也是比較簡單:

        • creating the context
        • providing the context
        • consuming the context

        creating the context

        首先在 src 目錄下創(chuàng)建一個(gè)名為 context 的文件夾,創(chuàng)建 index.tsx 文件通過 createContext ?來進(jìn)行創(chuàng)建操作

        import?{?createContext?}?from?'react';

        const?GlobalContext?=?createContext({})

        export?default?GlobalContext;

        providing the context

        接下來,在父組件中 providing the context,并且將之前編寫的 Custom Hooks(useBoolean)返回的 state 作為 value 值提供給子組件。

        import?SubApp?from?'./subApp';
        import?useBoolean?from?'./custom-hooks/useBoolean/index';
        import?GlobalContext?from?'./context/index'

        function?App()?{
        ??const?[state,?{?toggle,?setTrue,?setFalse?}]?=?useBoolean(true);

        ??return?(
        ????

        ??????

        Effects:{JSON.stringify(state)}</p>
        ??????


        ?????????toggle()}>
        ??????????Toggle
        ????????button>
        ????????type="button"?onClick={setFalse}?style={{?margin:?'0?16px'?}}>
        ??????????Set?false
        ????????</button>
        ????????
        ??????????Set?true
        ????????button>
        ??????</p>
        ??????/
        /?providing?the?context
        ??????></GlobalContext.Provider>
        ????div>
        ??)
        }

        export?default?App;

        consuming the context

        作為消費(fèi)方法其實(shí)有兩種,一種是通過 useContext(Context),另外一種是通過 Context.Consumer 提供一個(gè)特殊組件的渲染函數(shù)。

        通過 useContext(Context)

        子組件代碼編寫如下:

        import?{?useContext?}?from?'react'
        import?GlobalContext?from?'./context/index'

        const?SubApp?=?()?=>?{
        ??//?useContext
        ??const?val?=?useContext(GlobalContext)
        ??return?(
        ????

        ??????

        subEffects:{JSON.stringify(val)}</p>
        ????div>
        ??)
        }
        export?default?SubApp

        看起來這種實(shí)現(xiàn)方式也是比較簡單的,我們看看效果,當(dāng)我們點(diǎn)擊 Toggle 按鈕時(shí),發(fā)現(xiàn)在父子狀態(tài)進(jìn)行了共享,效果實(shí)現(xiàn)。

        通過 Context.Consumer

        接下里,試一下第二種方式,代碼如下:

        import?GlobalContext?from?'./context/index'

        const?SubApp?=?()?=>?{
        ??return?(
        ????

        ??????
        ????????{(val)?=>?

        subEffects:{JSON.stringify(val)}</p>}
        ??????GlobalContext.Consumer>
        ????</div>
        ??)
        }
        export?default?SubApp

        進(jìn)行相同的操作,也同樣實(shí)現(xiàn)了效果。

        拓展知識(shí)

        經(jīng)過上述兩個(gè)方法的實(shí)現(xiàn),基本上也解決了上篇文章提及的問題。在這里補(bǔ)充一下關(guān)于 context 的知識(shí)。

        對于我們創(chuàng)建的 context,就比如上文我創(chuàng)建的 GlobalContext,它可以擁有任意數(shù)量的Consumer。

        如果 GlobalContext 值發(fā)生變化(通過更改 Context.Provider 的 value 屬性 ),那么所有的 Consumer 都會(huì)立即收到通知并重新渲染。

        可能文字的表述不是很清楚,那么就以下列圖示來說明(圖畫的有點(diǎn)簡單,湊合下吧 hh)

        假設(shè)組件 APP 是我們的 Provider,底下組件 ABCE 都是它的 Consumer,那么當(dāng)我更改 Context.Provider 的 value 屬性時(shí),所有的 Consumer(這里指 ABCE)都會(huì)收到通知并重新渲染。

        細(xì)心的小伙伴可能發(fā)現(xiàn)了,不還有個(gè)組件 D 沒說嘛,下面就來說明:

        如果 Consumer 沒有被包裝在 Context.Provider 中,但仍然嘗試訪問 Context (使用 useContext(Context) 或 ),那么 Context 值拿到的是 createContext(defaultValue) 的默認(rèn)值 。

        const?GlobalContext?=?createContext({})

        如上述代碼,就比如之前創(chuàng)建的 GlobalContext,子組件如果被包裝在 GlobalContext.Provider 中,那么獲取的就是更改的 value 值,而如果沒有被包的話,就是獲取的默認(rèn)值(這里是 {})

        Context 該何時(shí)何地使用

        在上文,我們了解了 Context 使用好處,但我們應(yīng)該在哪個(gè)場景去使用它呢?難道不成就隨便用就好了?會(huì)給我們帶來什么問題呢?

        我們一步一步來回答上述問題。

        首先是我們應(yīng)該在哪個(gè)場景去使用它呢?

        一提到共享狀態(tài)以及本文中創(chuàng)建的也是 GlobalContext,就想到全局狀態(tài)了。

        我們可以存放一些全局狀態(tài),比如一些用戶基本信息,應(yīng)用的一些配置項(xiàng)(比如認(rèn)證,基本信息等),以及服務(wù)相關(guān)等等,這個(gè)就可以根據(jù)具體的業(yè)務(wù)需求來決定了。

        但是,在我們使用 Context 不得不考慮一下該怎樣使用它,難道真就隨便用?

        就以本文的代碼例子來說,我們通過了兩種方式在父子組件中實(shí)現(xiàn)狀態(tài)的共享,但是發(fā)現(xiàn)沒有,只要包括在 GlobalContext.Provider 其中的子組件,都必須使用 useContext(Context) 和 Context.Consumer 或者其它可能的方式來實(shí)現(xiàn)。

        如果子組件很多,那這樣層層環(huán)扣,豈不是影響的層級會(huì)比較多,而且在子組件中就會(huì)多增加一行代碼,整個(gè)樹結(jié)構(gòu)復(fù)雜性就會(huì)上升。

        當(dāng)然,如果子樹必須共享狀態(tài)或者組件內(nèi)有大量的計(jì)算,那么使用 Context 還是會(huì)方便許多,它可以減少一些沒必要的計(jì)算,直接共享就完事了。

        結(jié)尾

        那么,本文到此就結(jié)束了,你會(huì)期待接下來的文章嗎?

        我是【一百個(gè)Chocolate】,希望在文章中體現(xiàn)自己的思考,然后與大家分享,堅(jiān)持學(xué)習(xí)打卡,我們下期再見。

        -?END -

        如下是小獅子春秋招過程中學(xué)習(xí)整理的思維導(dǎo)圖以及 PDF 文檔,會(huì)不斷更新,目前已有 9?份思維導(dǎo)圖 + 335 頁筆記文檔,現(xiàn)在分享給大家,在公眾號后臺(tái)回復(fù)「小獅子」,關(guān)注領(lǐng)取


        學(xué)如逆水行舟,不進(jìn)則退

        點(diǎn)贊 + 在看,好文不白嫖嗷~

        瀏覽 47
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            天天夜夜综合 | 日日cαo | 男人添女人囗交视频 | 无码传媒| 天天射天天操天天 | 东京热一区二区三区 | 精品一级视频成人网站在线观看免费 | 欧美特黄视频 | 一区不卡 | 日韩高清无码免费观看 |