# Context-组件跨层级通信
Context 设计的目的是为了共享那些对于一个组件而言是 全局的数据。主要有以下 API。
# 1 React.createContext
创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。
import React from "react"
export const ColorContext=React.createContext({color:'red'})
export const ColorProvider=ColorContext.Provider;
export const ColorConsumer=ColorContext.Consumer;
export const UserContext=React.createContext();
export const UserProvider=UserContext.Provider;
export const UserConsumer=UserContext.Consumer;
2
3
4
5
6
7
8
只有 当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。将 undefined 传递给 Provider 的 value 时,消费组件的 defaultValue 不会生效。
# 2 Context.Provider
Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。
import React, { Component } from "react"
import { ColorProvider, UserProvider } from '../context'
export default class Color extends Component {
constructor (props) {
super(props)
this.state = {
theme: {
color: 'blue'
}, userInfo: {
name: 'james',
age: 18
}
}
}
render () {
const { theme, userInfo } = this.state;
return (
<div>
<ColorProvider value={theme}>
<UserProvider value={userInfo}>
</UserProvider>
</ColorProvider>
</div>
)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 3 Class.contextType
挂载在 class 上的静态属性 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。
注意: 一定要将使用当前组件包裹在 <MyContext.Provider> ,不然context value 不会被更新。
import React, { Component } from 'react'
import {ColorContext} from "../context/index"
export default class ContextTypePage extends Component{
static contextType=ColorContext
render(){
const {color} =this.context;
return(
<div className="border">
<h3 className={color}>ContextTypePage</h3>
</div>
)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 4 Context.Consumer
这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。
import React, { Component } from "react"
import { ColorConsumer, UserConsumer } from '../context';
export default class ColorConsumerPage extends Component {
render () {
return (
<div>
<ColorConsumer>
{context => (
<UserConsumer>
{userInfo => (
<div className={context.color}>
<p>{userInfo.name}</p>
<p>{userInfo.age}</p>
</div>
)}
</UserConsumer>
)}
</ColorConsumer>
</div>
)
}
}>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 5 Context.displayName
context 对象接受一个名为 displayName 的 property,类型为字符串。React DevTools 使用该字符串来确定 context 要显示的内容。
# 6 useContext()
除了以上 api列举的在子组件中获取父组件状态 2 种方法外,还有一种方式 useContext。该方法是 Hook 方法,不属于 Context 的 api。
当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider> 的 value prop 决定。
当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。
注意: 一定要将使用当前组件包裹在 <MyContext.Provider> ,不然context value 不会被更新。
const context = useContext(MyContext);