<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Custom Hooks 中使用 React Context

          共 3336字,需瀏覽 7分鐘

           ·

          2021-10-11 09:05

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

          關(guān)于 React Context

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

          const?value?=?useContext(MyContext);

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

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

          怎樣使用 Context

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

          • 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)方式也是比較簡(jiǎ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í)。

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

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

          可能文字的表述不是很清楚,那么就以下列圖示來說明(圖畫的有點(diǎn)簡(jiǎ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è)場(chǎng)景去使用它呢?難道不成就隨便用就好了?會(huì)給我們帶來什么問題呢?

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

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

          一提到共享狀態(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)扣,豈不是影響的層級(jí)會(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)在分享給大家,在公眾號(hào)后臺(tái)回復(fù)「小獅子」,關(guān)注領(lǐng)取


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

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

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产无毛| 国产精品女人18水真多 | 爱搞搞爱搞搞爱搞搞 | 天天干天天做天天综合 | 大鸡巴视频免费观看 |