官术网_书友最值得收藏!

3.1 Context

在React中,父組件通常將數(shù)據(jù)作為props傳遞給子組件。如果需要跨層級傳遞數(shù)據(jù),那么使用props逐層傳遞數(shù)據(jù)將會使開發(fā)變得復雜。同時,在實際開發(fā)中,許多組件需要一些相同的東西,如國際化語言配置、應用的主題色等,在開發(fā)組件的過程中也不希望逐級傳遞這些配置信息。

在這種情況下,可以使用React的Context特性。Context被翻譯為上下文,如同字面意思,其包含了跨越當前層級的信息。

Context在許多組件或者開發(fā)庫中有著廣泛的應用,如react-redux使用Context作為Provider,提供全局的store,以及React Router通過Context提供路由狀態(tài)。掌握Context將會對理解React Router起到極大的幫助作用。這里以圖3-1來說明Context如何跨組件傳遞數(shù)據(jù)。

在圖3-1中,左側(cè)組件樹使用了逐層傳遞props的方式來傳遞數(shù)據(jù),即使組件B、組件C不需要關心某個數(shù)據(jù)項,也被迫需要將該數(shù)據(jù)項作為props傳遞給子組件。而使用Context來實現(xiàn)組件間跨層級的數(shù)據(jù)傳遞,數(shù)據(jù)可直接從組件A傳遞到組件D中。

圖3-1 Context跨組件傳遞數(shù)據(jù)

在React v16.3及以上版本中,可使用React.createContext接口創(chuàng)建Context容器。基于生產(chǎn)者-消費者模式,創(chuàng)建容器后可使用容器提供方(一般稱為Provider)提供某跨層級數(shù)據(jù),同時使用容器消費方(一般稱為Consumer)消費容器提供方所提供的數(shù)據(jù)。示例如下:

通過setState改變count的值,觸發(fā)render渲染,Context.Provider會將最新的value值傳遞給所有的Context.Consumer。

在上例中,頂層組件App使用 CountContext.Provider將this.state.count的值提供給后代組件。App的子組件Toolbar不消費Provider所提供的數(shù)據(jù),Toolbar的子組件Button使用CountContext.Consumer獲得App所提供的數(shù)據(jù)count。中間層的Toolbar組件對數(shù)據(jù)跨層級傳遞沒有任何感知。在單擊“更新”按鈕觸發(fā)數(shù)據(jù)傳遞時,Toolbar中的“Toolbar render”信息不會被打印。每次單擊“更新”按鈕時,僅會打印“app render”與“Button render”,這是因為在Provider所提供的值改變時,僅Consumer會渲染,所以Toolbar中的“Toolbar render”不會被打印。

如果在Toolbar中也使用Provider提供數(shù)據(jù),如提供的value為500:

則Button中的Consumer得到的值將為500。原因在于當有多個Provider時,Consumer將消費組件樹中最近一級的Provider所提供的值。這作為React的一個重要特性,在React Router源碼中被大量應用。

注意,如果不設置Context.Provider的value,或者傳入undefined,則Consumer并不會獲得創(chuàng)建Context時的defaultValue數(shù)據(jù)。創(chuàng)建Context時的defaultValue數(shù)據(jù)主要提供給沒有匹配到Provider的Consumer,如果去掉App中的Provider,則Consumer所獲得的值為1。

如果希望使用this.context方式獲取Provider所提供的值,則可聲明類的靜態(tài)屬性contextType(React v16.6.0)。contextType的值為創(chuàng)建的Context,如:

在React v16.3以前,不支持通過createContext的方式創(chuàng)建上下文,可使用社區(qū)的polyfill方案,如create-react-context等。

注意,組件的優(yōu)化方法如shouldComponentUpdate或者React.memo不能影響Context值的傳遞。若在Button中引入shouldComponentUpdate,則會阻止Button更新:

改變Provider所提供的值后,依然會觸發(fā)Consumer的重新渲染,結(jié)果與未引入shouldComponentUpdate時一致。

主站蜘蛛池模板: 喜德县| 东宁县| 甘肃省| 德江县| 汝州市| 彰武县| 高陵县| 原阳县| 台州市| 丰宁| 鲁甸县| 民县| 太白县| 于都县| 清苑县| 米易县| 海门市| 姚安县| 龙江县| 乐业县| 高碑店市| 那曲县| 松溪县| 宜良县| 瑞昌市| 曲靖市| 石屏县| 邵阳市| 达孜县| 麻栗坡县| 同仁县| 晋城| 舒城县| 砚山县| 富宁县| 江口县| 潜江市| 金溪县| 九江市| 长子县| 安新县|