解決的問(wèn)題:context提供了一種在組件之間共享props的方式,而不必顯示地通過(guò)組件樹(shù)的逐層傳遞props
const MyContext = React.createContext('light');
<MyContext.Provider value='dark'>
<MyContext.Consumer>
{
context => <MyComponent {...context}>
}
</MyContext.Consumer>
</MyContext.Provider>
class.contextType
只能用在類(lèi)組件中,且只能訂閱單一的context數(shù)據(jù)來(lái)源
掛載在class上的contextType屬性會(huì)被重新賦值為一個(gè)由React.createContext()創(chuàng)建的Context對(duì)象。這樣就可以使用this.context來(lái)消費(fèi)最近Context上的那個(gè)值,可以在任何生命周期或者render中訪(fǎng)問(wèn)它。
使用:
MyClass.contextType = MyContext;
let value = this.context;
// 或者
static contextType = MyContext;
<Button them={this.context}/>
API:
React.createContext
當(dāng)訂閱了這個(gè)context對(duì)象,組件會(huì)從組件樹(shù)中距離自身最近的那個(gè)provider中讀取到當(dāng)前的context值
只有當(dāng)組件樹(shù)中沒(méi)有匹配到provider時(shí),defaultValue參數(shù)才生效。
Context.Provider
每個(gè)context對(duì)象都會(huì)返回一個(gè)provider React組件,允許消費(fèi)組件訂閱context變化;
provider 接受一個(gè)value屬性,傳遞給消費(fèi)者;一個(gè)provider可以對(duì)應(yīng)多個(gè)消費(fèi)者;
多個(gè)provider可以嵌套,里層會(huì)覆蓋外層;
當(dāng)provider的value值發(fā)生變化時(shí),它內(nèi)部所有的消費(fèi)組件都會(huì)重新渲染;provider及內(nèi)部consumer組件不受shouldComponentUpdate函數(shù)限制
通過(guò)檢測(cè)新舊值變化使用了object.is
注意事項(xiàng):
因?yàn)閏ontext會(huì)使用參考標(biāo)識(shí)來(lái)決定何時(shí)進(jìn)行渲染,這時(shí)當(dāng)provider的父組件進(jìn)行重新渲染時(shí),會(huì)造成consumer組件重新渲染,因?yàn)関alue總會(huì)被賦予新對(duì)象:
<MyContext.Provider value={{something: 'something'}}>
<Toolbar />
</MyContext.Provider>
//將value提升到父組件的state里邊
this.state = {
value: {something: 'something'},
};
<Provider value={this.state.value}>
<Toolbar />
</Provider>
==========================================
useContext:接收一個(gè)context對(duì)象并返回該context的當(dāng)前值。當(dāng)前context值由上層組件中距離當(dāng)前組件最近的MyContext.Provider的value prop決定,useContext(MyContext) 能夠讀取 context 的值以及訂閱 context 的變化
當(dāng)上層最近的MyContext.Provider更新時(shí),該hook會(huì)出發(fā)重新渲染,并使用傳遞給MyContext.Provider的value的最新值,即使祖先使用 React.memo 或 shouldComponentUpdate,也會(huì)在組件本身使用 useContext 時(shí)重新渲染
注意事項(xiàng):
調(diào)用了 useContext 的組件總會(huì)在 context 值變化時(shí)重新渲染。如果重渲染組件的開(kāi)銷(xiāo)較大,你可以 通過(guò)使用 memoization 來(lái)優(yōu)化
正確使用方法?:useContext(MyContext)
需要在上層組件樹(shù)中使用 <MyContext.Provider> 來(lái)為下層組件提供 context