譯文:深入了解React Context

(原文鏈接:https://css-tricks.com/digging-into-react-context/)...其實并不深入,但不失為一篇好文章。

????????最近你可能想知道關于context的一些消息,想知道它對于你和你的react項目可能意味著什么?context出現之前,在狀態管理變得異常的復雜,超出了setState的能力的時候,你可能不得不使用第三方庫。感謝優秀的React團隊最近作出的更新,現在React本身的context可以幫助我們解決一些狀態管理方面的問題了。

context解決了什么事情?

? ? ?你怎樣將state傳遞給一個在嵌套的組件樹中的一個子組件,可能你知道你可以用Redux去管理狀態,但你沒必要在任何情況下都去使用Redux。有一個可以不用Redux也不用第三方庫的方法,你可以使用props。

? ? ?加入你要實現的功能具有類似于下面的這種結構:

? ? ? 這些狀態在APP組件中,并且在UserProfile和UserDetails組件中也是需要的,你需要利用props將它傳遞到樹的底層,如果需要這個state的組件在樹的第十層,那這樣的工作會讓人感到乏味、疲憊,并且也非常容易出錯。每一個組件都應該像一個黑盒子,其他組件不應該知道它們不需要的狀態。這是一個和上述情況相匹配的一個程序實例。(譯者述:很抱歉這里用截圖的形式展示代碼,由于代碼插入的功能不能支持JS自定義的組件,故采用截圖的形式展現。如若想本地嘗試,可點擊原文,獲取可復制的源碼)

? ? ? 我們使用了props來將state傳遞給另一個組件,User 組件不需要這個state,但是為了將state傳遞到組件樹的底層,它也通過props收到了這個state。

Context來幫忙了

? ? ? 通過React的Context API,你可以將state存儲在應用程序的全局狀態中,并僅在需要的組件中訪問它,而不需要利用props一層層地往組件樹底層傳遞。

首先,我們可以利用React.createContext()來初始化一個新的Context。

? ? ? 這個新的Context由const來聲明,即圖中的UserContext,你可以看到,我們無需安裝任何的第三方的庫,React V16.3.0及以上版本已經有Context API了。Provider組件使得需要context內容的組件(訂閱者)能夠獲取它,換句話說,Provider組件允許消費者訂閱context中的更改。請記住,context就類似于全局應用程序狀態。因此,不是消費者的組件不會獲取到context內容。

? ? ? 如果你在本地嘗試,那你的context 文件應該類似于下圖:

Provider

? ? ? 我們將在我們的父組件中使用Provider,在該組件中我們有state需要傳遞

? ? ? Provider 接受一個value作為props來傳遞給底層的消費者組件,在本文的示例中,我們將user這個狀態傳遞給消費者組件。你可以看到,我們并沒有將它作為props傳遞給User組件。這也意味著我們可以在不需要props的情況下編輯User組件,因為它本身也不需要它們。

消費者(Consumer)

? ? ? 多個消費者組件可以訂閱一個Provider組件,我們的UserProfile需要利用context,所以我們讓它來訂閱、觀察Provider。

? ? ? 我們通過value props的方式注入到Provider中的數據將在函數的context參數中能獲取到,現在我們可以使用這種方法在我們的組件中獲取到用戶的姓名。

? ? ? UserDetail組件現在看起來很像UserProfile,因為它們訂閱的是同一個Provider。


更新state

? ? ? 如果我們允許用戶更改他們的姓名怎么辦,這也是可行的。當通過Provider組件傳遞過來的值改變的時候,consumer(消費者)組件會重新渲染。在消費者組件組件中,我們將有兩個輸入框,分別用于名字與姓氏。在Provider組件中,我們有兩個函數,接收從輸入框中輸入的值,用于更新應用程序的狀態。

? ? ? APP組件源碼見下圖:

? ? ? ?我們將含有state和action的對象傳遞給Provider接受的value props的Provider。這些actions就是當onChange事件發生的時觸發的觸發的函數,事件發生得到的值可以用來更新state,因為我們想要更新的是名字和姓氏,而不需要其他值,基于此,我們利用ES6的擴展操作符,它允許我們更新指定的值。

? ? ? 有了這些變化,我們也需要更新UserProfile組件。

我們使用ES6的解構來提取從Provider中獲取到的值中的state

? ? ? 對于UserDetails組件,既有state又有actions,需要加入兩個輸入框,并且監聽它們的onChange事件,從而去觸發相應的反應函數。

使用默認值

? ? ? 初始化context的時候我們可以傳遞一些默認值。所以我們可以在context中傳遞一些數據(默認值)而不是一個空對象。

? ? ? 要在組件樹種使用這些數據,我們必須從樹中刪除Provider。所以我們的APP組件應該是這樣的:

? ? ? 初始化新的context時,這些數據將被用于consumer(消費者)組件中。

總結

? ? ? 當事情變得越來越復雜,你嘗試著yarn install第三方的狀態管理庫的時候,請暫停幾秒,你可以利用React context。不相信我?也許你會相信Kent C. Dodds.

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,748評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,165評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,595評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,435評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,943評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,175評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,713評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,599評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,788評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,034評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,408評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,747評論 2 370

推薦閱讀更多精彩內容