Context 是什么
上下文,容器,多个地方传递数据,程序在执行的地候可以访问的容器,给整个组件树共享全局的数据
Provider 供应方
consumer 消费方 ,使用方
context.js
import React from "react";
const ThemeContext = React.createContext("black");
export { ThemeContext };
供应方,父组件
import React, { Component, lazy, Suspense } from "react";
import Page1 from "./view/page1";
import { ThemeContext } from "./context";
export default class App extends Component {
state = {
theme: "red",
};
render() {
return (
<div>
<ThemeContext.Provider value={this.state.theme}>
<Page1 />
</ThemeContext.Provider>
</div>
);
}
}
使用方,子组件
import React, { Component } from "react";
import { ThemeContext } from "../context";
export default class page1 extends Component {
render() {
return (
<div>
<ThemeContext.Consumer>
{(theme) => <div>{theme}</div>}
</ThemeContext.Consumer>
</div>
);
}
}
Context与组合的应用场景与使用问题
给整个组件树共享全局的数据
static contextType = ThemeContext;
- 将上下文的类型指定为 ThemeContext,this.context -> theme
- 向上找最近的 ThemeContext 的Provider ,并且取到theme值
import React, { Component } from "react";
import { ThemeContext } from "../context";
export default class page1 extends Component {
static contextType = ThemeContext;
render() {
return <div>{this.context}</div>;
}
}
总结:
- 最适合的场景:杂乱无章的组件都需要同一些数据,比如:主题
- 单纯为了不层层传递属性的话,Context 实际上不合适,可以用组件组合,把整个
- 组件作为props传递
- Context弱点:弱化及污染组件的纯度,导致组件复用性降低
Context API
const Acontext = React.CreateContext ('default a')
Acontext.displayName = 'MyAContext' //这个主要是针对 dev tools 显示用的
React.CreateContext
- 创建一个指定的Context 对象
- 组件会找离自己最近的Provider,获取其 value
- 没有匹配到Provider 就使用 default value,其他情况均不使用默认参数
Context.Provider
- 通过React.CreateContext ,上下文对象里的一个组件
- Proivder 组件可以插入其他组件,订阅这个Context
- 通过Provider 的value 属性来将数据传递 给 Consumer 组件
- value 变化后,插入Provider的组件都会重新渲染
- 新值与旧值 比较 是用了与 object.is 相同的算法
Context.Consumer
- 使用 Provider的 value,订阅context 的变更
- Consumer 使用函数作为子元素 -> function as a child
- 函数接收context 最近的provider 提供的value
- 没有provider 会找default value
contextType
- class静态属性
- contextType ->React.createContext() 生成的 context对象
- static contextType = themeContext (给当前环境下的context重新指定新的引用)
- 在生命周函数 和render函数中都可以访问