demos源码
Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据。

如何使用

  1. 将初始状态传递给 React.createContext。这个方法会返回一个带有 Provider 和 Consumer 的对象。
  2. 使用 Provider 组件包裹在组件树的最外层,并接收一个 value 属性。value 属性可以是任何值。
  3. 使用 Consumer 组件,在组件树中 Provider 组件内部的任何地方都能获取到状态的子集。

ThemeContext:

1
2
3
4
5
6
import React from 'react';
const ThemeContext = React.createContext({
theme: "red"
});

export default ThemeContext;

ContextCom:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from "react";
import ChildCom from "./ChildCom";

import ThemeContext from "./ThemeContext";

class ContextCom extends Component {
render() {
return (
<div>
<ThemeContext.Provider value={{theme: 'pink'}}>
<ChildCom />
</ThemeContext.Provider>
</div>
);
}
}

export default ContextCom;

ChildCom:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { Component } from 'react'
import ThemeContext from "./ThemeContext";

class ChildCom extends Component {
render() {
return (
<ThemeContext.Consumer>
{
context => (
<div>this.theme: {context.theme}</div>
)
}
</ThemeContext.Consumer>
)
}
}

export default ChildCom;

注意点

  1. 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数。
  2. Context.Consumer需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。

Class.contextType

可以通过Class.contextType直接将Context 对象挂载到class的contextType属性,然后就可以使用this.context对context对象进行使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from "react";
import TestThemeContext from "./TestThemeContext";

class ContextTypeChildCom extends Component {
render() {
return <div>{JSON.stringify(this.context)}</div>;
}
componentDidMount() {
console.log(this.context);
}
}

ContextTypeChildCom.contextType = TestThemeContext;

export default ContextTypeChildCom;

如何更新Context的值呢

可以通过 context 传递一个函数,使得 consumers 组件更新 context:
ContextComProVider:

1
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
class ContextComProVider extends Component {
constructor(props) {
super(props);

this.state = {
theme: "pink",
toggleTheme: this.toggleTheme
};
}

toggleTheme = value => {
console.log(value);
this.setState(state => ({
theme: value
}));
};

render() {
return (
<div>
<ThemeContext.Provider value={this.state}>
<ChildCom />
</ThemeContext.Provider>
</div>
);
}
}

childCom:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component } from 'react'
import ThemeContext from "./ThemeContext";

let arr = ['red_','pink_','green_'];

class ChildCom extends Component {
render() {
return (
<ThemeContext.Consumer>
{
({theme, toggleTheme}) => (
<div onClick={() => {toggleTheme(arr[Math.floor(Math.random() * 3)])}}>this.theme: {theme}</div>
)
}
</ThemeContext.Consumer>
)
}
}

export default ChildCom;