最近在整理CSS自定義屬性在React中的使用時了解到“可以使用React Context API相關(guān)的知識更好的在React組件中使用CSS自定義屬性”,但是自己對這方面的知識了解的并不多,因此想借此機會來學(xué)習(xí)React Context API相關(guān)的知識。愛掏網(wǎng) - it200.com也基于這個原因有了這篇文章。愛掏網(wǎng) - it200.com
我們從一個React的實例開始。愛掏網(wǎng) - it200.com假設(shè)你要構(gòu)建一個React的應(yīng)用,該應(yīng)用有一個最簡單的功能,就是Dark Mode的切換。愛掏網(wǎng) - it200.com簡單地說,在Web應(yīng)用上一個切換組件(比如ThemeToggle
),用戶點擊該切換按鈕可以讓頁面在暗色系(dark
)和亮色系(light
)之間切換。愛掏網(wǎng) - it200.com
通常我們會通過props
為所有組件提供當(dāng)前主題的模式,并使用state
來更新當(dāng)前的主題。愛掏網(wǎng) - it200.com
在/src/components/
目錄下分別創(chuàng)建了GrandChild
、Child
、ParentComponent
和ThemeToggle
幾個組件:
示例代碼如下:
// /src/components/GrandChild
import React from 'react'
const GrandChild = (props) => {
const styled = {
color: `${props.theme.color}`,
background: `${props.theme.background}`
}
return Theme Toggle
}
export default GrandChild;
// /src/components/Child
import React from 'react'
import GrandChild from '../GrandChild'
const Child = (props) => {
const styled = {
border: `5px solid ${props.theme.color}`,
padding: `10vmin 20vmin`,
borderRadius: '8px'
}
return
}
export default Child
// /src/components/ParentComponent
import React from 'react'
import Child from '../Child'
const ParentComponent = (props) =>
export default ParentComponent
// /src/components/ThemeToggle
import React from 'react'
const ThemeToggle = (props) => {
const styled = {
background: `${props.theme.background}`,
color: `${props.theme.color}`,
border: `4px solid currentColor`,
borderRadius: `6px`,
padding: `2vmin 4vmin`,
margin: `4vmin`,
cursor: `pointer`
}
return
}
export default ThemeToggle
// /src/App.js
import React, {Fragment} from 'react';
import ParentComponent from './components/ParentComponent'
import ThemeToggle from './components/ThemeToggle'
const dark = {
background: '#121212',
color: '#fff'
}
const light = {
background: '#fff',
color: '#444'
}
const App = () => {
const [theme, setTheme] = React.useState('light')
const onClickHander = () => {
theme === 'light' ? setTheme('dark') : setTheme('light')
}
return
}
export default App;
效果如下:
在這個示例中,在ParentComponent
組件中指定了theme
這個props
,并且將這個props
一級一級往下傳,傳給組件樹下的所有組件。愛掏網(wǎng) - it200.com即,將theme
傳遞到需要它的地方,在本例中會傳到GrandChild
組件。愛掏網(wǎng) - it200.com而Child
組件和theme
(props
)沒有任何關(guān)系,它只是作為一個媒體而以。愛掏網(wǎng) - it200.com
試想一下,在React中組件樹就有點類似于我們熟悉的DOM樹:
正如上圖所示,我們可以在最底層組件中添加state
,但如果要將數(shù)據(jù)傳遞給兄弟組件的話,在React Context API之前,我們只能將state
放到他們的父組件中(組件樹中更高的組件位置),然后通過props
將其傳遞回同級組件:
就像上面的示例,我們需要將state
從組件樹的最頂層一級一級往下傳,哪怕是所有中間層組件不需要使用這些數(shù)據(jù),但它必須為了后面的組件做為媒介,將state
傳遞到最底層組件。愛掏網(wǎng) - it200.com
對應(yīng)到上面的示例中,那就是:
React Context API正是用來解決Prop Drilling的問題。愛掏網(wǎng) - it200.comReact Context API提供了一種通過Provider
和Consumer
用來提供數(shù)據(jù)和消費數(shù)據(jù),它們可以在組件件中傳遞數(shù)據(jù),最主要的是不必要一級一級的通過props
向組件樹傳遞state
。愛掏網(wǎng) - it200.com簡單地說,在組件樹最頂層的組件中通過Provider
提供數(shù)據(jù),在后面的任何一個子組件樹可以通過Consumer
來消費Provider
提供的數(shù)據(jù):
React的官網(wǎng)是這樣描述Context的:
在這個特性還沒出現(xiàn)之前,在React應(yīng)用中數(shù)據(jù)的通訊是通過props
屬性自上而下(由父及子)進行傳遞的,換句話說,必須通過props
傳遞到每個組件中,然后在組件中重復(fù)相同的過程。愛掏網(wǎng) - it200.com但這種做法對于某些類型的屬性而言是極其繁鎖的,也會變得非常的糟糕,最終可能會導(dǎo)致props
在我們的組件中要不斷的一層一層嵌套。愛掏網(wǎng) - it200.com
React Context API的出現(xiàn)主要是為了幫助我們解決這方面的問題,它提供了一種在組件之間共享此類值的方式,而不必顯式地通過組件樹的逐層傳遞props
。愛掏網(wǎng) - it200.com也就是說,它允許父組件隱式地將數(shù)據(jù)傳遞給子組件(不管組件樹有多深)。愛掏網(wǎng) - it200.com換句話說,可以將數(shù)據(jù)添加到父組件中,然后任何子組件都可以訪問它。愛掏網(wǎng) - it200.com
假設(shè)我們有這樣的一個使用場景,在一個React應(yīng)用中,我們有App
、Container
、Form
和Button
四個組件,它們之間是依次被嵌套:
App ? Container ? Form ? Buttton
假如我們使用props
傳遞就需要一層一層往里傳:
換成Context
,就可以直接獲取最頂層App
組件綁定的值:
對于像我這樣的初級使用者而言,要想徹底的了解React Context API,只能從最簡單的應(yīng)用開始。愛掏網(wǎng) - it200.com為了更好的理解它的使用,我們從最簡單的示例開始。愛掏網(wǎng) - it200.com
創(chuàng)建上下文對象
在React中使用Context的話,我們首要做的就是創(chuàng)建上下文對象(Context Object)。愛掏網(wǎng) - it200.com可以使用React
上的.createContext()
創(chuàng)建一個Context
對象:
const DataContext = React.createContext()
嘗試著把這個Context
對象DataContext
在控制臺上打印出來:
這個時候可以從組件樹中離自身最近的那個匹配的Prrovider
中讀取到當(dāng)前的context
值。愛掏網(wǎng) - it200.com
只有當(dāng)組件所處的樹中沒有匹配到Provider
時,其defaultValue
參數(shù)才會生效。愛掏網(wǎng) - it200.com這有助于在不使用Provider
包裝組件的情況下對組件進地測試。愛掏網(wǎng) - it200.com
另外,createContext()
方法提供了Provider
和Consumer
能力,其中一個是提供者,另一個是消費者,而且這兩個屬性都是成對出現(xiàn)的,即每一個Provider
都會有對應(yīng)的一個Consumer
。愛掏網(wǎng) - it200.com
Provider
將作為父組件使用,它持有所有Consumer
都可以共享的值。愛掏網(wǎng) - it200.com注意,Consumer
只能用于Provider
的子組件。愛掏網(wǎng) - it200.com
使用Provider
提供數(shù)據(jù)
上一步,使用React.createContext()
創(chuàng)建了一個名為DataContext
的上下文對象,在其中,我們用一些值(value
)初始化一個狀態(tài)(state
),可以使用DataContext
的Provider
接受一個value
屬性,傳遞給子組件消費(Consumer
)
const App = () => Child Component
;
Provider
的value
屬性的值可以是字符串、數(shù)字或?qū)ο蟆?b class="xhide">愛掏網(wǎng) - it200.com
消費Provider
提供的數(shù)據(jù)
Provider
創(chuàng)建了數(shù)據(jù),其創(chuàng)建的數(shù)據(jù)可以通過context
對象的Consumer
屬性給子組件消費。愛掏網(wǎng) - it200.com主要有三種方法來消費Provider
屬性創(chuàng)建的數(shù)據(jù)。愛掏網(wǎng) - it200.com
使用Consumer
組件消費數(shù)據(jù)
創(chuàng)建一個新組件,并且在該組件中使用DataContext
的Consumer
來消費數(shù)據(jù)。愛掏網(wǎng) - it200.com這將返回一個函數(shù),該函數(shù)允許組件消費Provider
中設(shè)置的值。愛掏網(wǎng) - it200.com比如:
const ParagraphChildComponent = () =>
{ value => I'm {value.userName}, {value.age}
包月會員查看