解决的问题:context提供了一种在组件之间共享props的方式,而不必显示地通过组件树的逐层传递props
const MyContext = React.createContext('light');
<MyContext.Provider value='dark'>
<MyContext.Consumer>
{
context => <MyComponent {...context}>
}
</MyContext.Consumer>
</MyContext.Provider>
class.contextType
只能用在类组件中,且只能订阅单一的context数据来源
挂载在class上的contextType属性会被重新赋值为一个由React.createContext()创建的Context对象。这样就可以使用this.context来消费最近Context上的那个值,可以在任何生命周期或者render中访问它。
使用:
MyClass.contextType = MyContext;
let value = this.context;
// 或者
static contextType = MyContext;
<Button them={this.context}/>
API:
React.createContext
当订阅了这个context对象,组件会从组件树中距离自身最近的那个provider中读取到当前的context值
只有当组件树中没有匹配到provider时,defaultValue参数才生效。
Context.Provider
每个context对象都会返回一个provider React组件,允许消费组件订阅context变化;
provider 接受一个value属性,传递给消费者;一个provider可以对应多个消费者;
多个provider可以嵌套,里层会覆盖外层;
当provider的value值发生变化时,它内部所有的消费组件都会重新渲染;provider及内部consumer组件不受shouldComponentUpdate函数限制
通过检测新旧值变化使用了object.is
注意事项:
因为context会使用参考标识来决定何时进行渲染,这时当provider的父组件进行重新渲染时,会造成consumer组件重新渲染,因为value总会被赋予新对象:
<MyContext.Provider value={{something: 'something'}}>
<Toolbar />
</MyContext.Provider>
//将value提升到父组件的state里边
this.state = {
value: {something: 'something'},
};
<Provider value={this.state.value}>
<Toolbar />
</Provider>
==========================================
useContext:接收一个context对象并返回该context的当前值。当前context值由上层组件中距离当前组件最近的MyContext.Provider的value prop决定,useContext(MyContext) 能够读取 context 的值以及订阅 context 的变化
当上层最近的MyContext.Provider更新时,该hook会出发重新渲染,并使用传递给MyContext.Provider的value的最新值,即使祖先使用 React.memo
或 shouldComponentUpdate
,也会在组件本身使用 useContext
时重新渲染
注意事项:
调用了 useContext
的组件总会在 context 值变化时重新渲染。如果重渲染组件的开销较大,你可以 通过使用 memoization 来优化
正确使用方法✅:useContext(MyContext)
需要在上层组件树中使用 <MyContext.Provider> 来为下层组件提供 context