前言
在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
Context使用有两种方式:
Class.contextTypeContext.Consumer
区别在于:Class.contextType只能共享一个Context对象,而Context.Consumer可以共享多个Context对象
使用逻辑:
第一步:定义Context对象,注意,这里的light为Context默认值
const ThemeContext = React.createContext('light');
第二步:父组件向下传递Context
// 传递一个
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
// 传递多个
<ThemeContext.Provider value={dark}>
<UserContext.Provider value={{ name:'张三', sex:'男' }}>
<Layout />
</UserContext.Provider>
</ThemeContext.Provider>
// 第三步:子组件获取Context
// 获取一个
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
// 获取多个
function Content() {
return (
<ThemeContext.Consumer>
{(theme) => (
<UserContext.Consumer>
{(user) => <ProfilePage user={user} theme={theme} />}
</UserContext.Consumer>
)}
</ThemeContext.Consumer>
);
}
Class.contextType:只能共享一个Context对象
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
import React from "react";
const ThemeContext = React.createContext("light");
class App extends React.Component {
render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
Context.Consumer:可以共享多个Context对象
// Theme context,默认的 theme 是 “light” 值
const ThemeContext = React.createContext("light");
// 用户登录 context
const UserContext = React.createContext({
name: "Guest",
});
class App extends React.Component {
render() {
const { signedInUser, theme } = this.props;
// 提供初始 context 值的 App 组件
return (
<ThemeContext.Provider value={theme}>
<UserContext.Provider value={signedInUser}>
<Layout />
</UserContext.Provider>
</ThemeContext.Provider>
);
}
}
function Layout() {
return (
<div>
<Sidebar />
<Content />
</div>
);
}
// 一个组件可能会消费多个 context
function Content() {
return (
<ThemeContext.Consumer>
{(theme) => (
<UserContext.Consumer>
{(user) => <ProfilePage user={user} theme={theme} />}
</UserContext.Consumer>
)}
</ThemeContext.Consumer>
);
}
动态Context,即父组件Context值改变,层层子组件接收Context也会改变
只需将Context向下传递的值定义在state中即可
import React, { Component } from "react";
class ContextType extends Component {
constructor() {
super();
this.state = {
theme: {backGround: '#ffffff', color: '#222222'}
};
}
// 更改theme值
handleThemeSwitch() {}
render() {
return (
<div className="contextType">
<h4>使用 Context - ContextType 实现全局样式</h4>
<button onClick={this.handleThemeSwitch.bind(this)}>主题切换</button>
<div className="container">
<ThemeContext.Provider value={this.state.theme}>
<Toolbar />
</ThemeContext.Provider>
</div>
</div>
);
}
}