react基础-Context

93 阅读2分钟

前言

在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。

Context使用有两种方式:

  • Class.contextType
  • Context.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>
    );
  }
}