通常在 React 组件中,我们会使用 props 来自上而下(父传子)的传递属性。但是当组件层级太深时,或者某些属性是应用中很多组件都需要使用的,比如UI主题等,使用传统的 props 来处理就会显得非常麻烦。而 Context 就提供了一种组件间信息共享的解决方式,从而避免了通过 props 的逐层传递。
1. 生产者
React.createContext:创建一个 Context 对象;
const MyContext = React.createContext(defaultValue);
Context.Provider:每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
<MyContext.Provider value={/* 某个值 */}>
<MyClass />
</MyContext.Provider>
2. 消费者
Class 组件消费
import React from 'react'
class MyClass extends React.Component {
render() {
let value = this.context;
/* 基于 MyContext 组件的值进行渲染 */
}
}
MyClass.contextType = MyContext;
函数组件使用 Consumer 消费
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
函数组件使用 useContext 来消费
const value = useContext(MyContext);
示例
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
// 定义 Context
const ThemeContext = React.createContext(themes.light);
function App() {
return (
// 使用 ThemeContext.Provider 组件进行包裹,子组件就能消费 ThemeContext
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar(props) {
return (
<div>
<ThemedButtonFunc />
<ThemedButtonFuncConsumer />
<MyClass />
</div>
);
}
// 函数组件使用 useContext 进行消费
function ThemedButtonFunc() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
// 函数组件使用 ThemeContext.Consumer 进行消费
function ThemedButtonFuncConsumer() {
return (
<ThemeContext.Consumer>
{
theme => (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
)
}
</ThemeContext.Consumer>
);
}
// class 组件使用 contextType 进行消费
class MyClass extends React.Component {
render() {
let theme = this.context;
/* 基于 MyContext 组件的值进行渲染 */
return (
<button style={{ background: theme.background, color: theme.foreground }}>
I am styled by theme context!
</button>
);
}
}
MyClass.contextType = ThemeContext;