父子間組件通信
父結點數據傳遞給子組件 通過 props進行傳遞,子組件只能用于展示或者判斷盔然,但不能進行更新
當子組件需要通知父組件數據變化時,父組件通過把函數作為一個props傳遞持偏,子組件只需要按需調用就可以了
非父子組件間通信
ContextAPI 在頂層進行數據定義蹂喻,在這個組件樹的所有組件就能通過 Context 的API進行獲取和修改
Context 提供了一個無需為每層組件手動添加 props筏餐,就能在組件樹間進行數據傳遞的方法开泽。
React.createContext
創(chuàng)建一個 Context 對象。
const MyContext = React.createContext(defaultValue);
defaultValue
不止是一個值魁瞪,也可以是一個對象{value穆律,changeValue()} 也可以提供這樣的方法進行修改value
當 React 渲染一個訂閱了這個 Context 對象的組件,這個組件會從組件樹中離自身最近的那個匹配的 Provider 中讀取到當前的 context 值导俘。
只有當組件所處的樹中沒有匹配到 Provider 時峦耘,其 defaultValue 參數才會生效。
這有助于在不使用 Provider 包裝組件的情況下對組件進行測試旅薄。
注意:將 undefined 傳遞給 Provider 的 value 時辅髓,消費組件的 defaultValue 不會生效。
Context.Provider
<MyContext.Provider value={/* 某個值 */}>
<消費組件 />
</MyContext.Provider>
每個 Context 對象都會返回一個 Provider React 組件少梁,它允許消費組件訂閱 context 的變化洛口。
Provider 接收一個 value 屬性,傳遞給消費組件凯沪。一個 Provider 可以和多個消費組件有對應關系第焰。
多個 Provider 也可以嵌套使用,里層的會覆蓋外層的數據妨马。
當 Provider 的 value 值發(fā)生變化時挺举,它內部的所有消費組件都會重新渲染。
Provider 及其內部 consumer 組件都不受制于 shouldComponentUpdate 函數烘跺,因此當 consumer 組件在其祖先組件退出更新的情況下也能更新湘纵。
當Provider所在的父組件進行重新渲染時,會導致下邊所有消費組件全部重新渲染滤淳,即使Provider的value沒有發(fā)生改變瞻佛。為了避免這種事情的發(fā)生,
可以考慮把Provider的value先綁定在父組件的state上。這樣當父組件進行重新渲染時就不會發(fā)生因為value是一個新對象而引發(fā)消費組件的渲染伤柄。
這個是官方的解釋绊困,但實質上并不是這樣。
Context.Provider說到底還是組件适刀,也按照組件基本法來辦事秤朗,當value發(fā)生變化時,它也可以不引發(fā)子組件的渲染笔喉。
前提是取视,子組件作為一個屬性(this.props.children)也要保持不變才行。
如果子組件變了常挚,Context.Provider 也不知道你是不是以前的你作谭,只好讓你重畫了。
看官網中的注意事項的時候能夠發(fā)現給出的代碼中Provider變成了一個單獨的組件奄毡,對于獨立的Provider組件內部構成并沒有說明折欠。
具體解釋:https://zhuanlan.zhihu.com/p/50336226
const MyContext = React.createContext('light');
class Provider extende React.Component{
constructor(){
this.state = {
value:'dark'
}
}
render (){
return (
<MyContext.Provider value={this.state.value}>
{this.props.children}
</MyContext.Provider>
)
}
}
class MyContextRoot extende React.Component{
render (){
return (
<Provider>
<Child />
</Provider>
)
}
}
Class.contextType
掛載在 class 上的 contextType 屬性會被重賦值為一個由 React.createContext() 創(chuàng)建的 Context 對象。
注意這種方法只能掛載一個context吼过,如果需要多個锐秦,只能使用Context.Consumer進行多層嵌套
方法一:
這能讓你使用 this.context 來消費最近 Context 上的那個值。
你可以在任何生命周期中訪問到它盗忱,包括 render 函數中酱床。
class MyClassContext extende Component {
var value = this.context;
}
MyClassContext.contextType = MyContext
方法二:
可以通過static方法綁定(class Fields)
class MyClassContext extende Component{
static mycontext = MyContext;
}
Context.Consumer
一個 React 函數式組件 可以訂閱 context 的變更,這讓你在函數式組件中可以訂閱 context趟佃。
同時 類組件也通過這種方式訂閱多個Context
function MyFuncContext(){
return (
<MyContext.Consumer>
{(value)=>({
<span>{value}</span>
})}
</MyContext.Consumer>
)
}
這種方法需要一個函數作為子元素(function as a child)扇谣。
這個函數接收當前的 context 值,并返回一個 React 節(jié)點闲昭。
傳遞給函數的 value 值等價于組件樹上方離這個 context 最近的 Provider 提供的 value 值揍堕。
如果沒有對應的 Provider,value 參數等同于傳遞給 createContext() 的 defaultValue汤纸。
Context.displayName
context 對象接受一個名為 displayName 的 property衩茸,類型為字符串。React DevTools 使用該字符串來確定 context 要顯示的內容贮泞。
const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';