Context 概念

  1. 上下文 (Context)React 中一个重要的特性,它允许在组件树中共享数据,而不必通过每个级别显式地传递参数;
  2. 这是一种将数据传递到树中任意深度的组件的方法,无论其祖先组件是否知道该数据;

Context 特点

  1. 跨级传递数据Context 允许在组件树中任意深度传递数据,而不必每层手动传递 props

  2. 避免多余的层次:通过 Context 可以避免将数据传递到组件树中不需要它的组件;

  3. 易于管理Context 允许在一个地方管理数据,而不必在每个组件中手动管理;

参数介绍

createContext

  1. 创建一个 Context 对象,当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值;

  2. 只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效;这有助于在不使用 Provider 包装组件的情况下对组件进行测试;

  3. 注意:将 undefined 传递给 Providervalue 时,消费组件的 defaultValue 不会生效;

const MyContext = React.createContext(defaultValue);

Provider

  1. 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化;Provider 接收一个 value 属性,传递给消费组件;

  2. 一个 Provider 可以和多个消费组件有对应关系,多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据;

export const MyContext = React.createContext();

class App extends React.Component {
  render () {
    return (
      // 在根节点提供了一个全局对象,对象连具有 color 属性
      <MyContext.Provider value={{ color: 'red' }}>
        <Child />
      </MyContext.Provider>
    ); 
  }
}

Consumer、contextType

  1. Consumer 消费

    1. React 组件可以订阅到 context 变更,这能在 函数式组件 中完成订阅 context
    2. 这里需要 函数作为子元素 (function as child) 这种做法;
  2. contextType 消费

    1. 在类组件中使用静态属性 contextType 接收 context
    2. 这样可以在 render 以外的地方使用 context 了;
JSX
JavaScript
import { MyContext } from "./grandFather-context";

<MyContext.Consumer>
  {({ color }) => (
    // 这里可以正常返回 jsx 代码
    <div style={{ color }}>
      Hello World!
    </div>
  )}
</MyContext.Consumer>
import { MyContext } from "./grandFather-context";

class MyClass extends React.Component {
  // static contextType = MyContext;

  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}

MyClass.contextType = MyContext;

使用场景

  1. 主题色切换;

  2. 多国语言切换,也就是国际化;

  3. 祖孙组件之间的传值;

案例:表单

JavaScript
JavaScript
JavaScript
JavaScript
JavaScript
JavaScript
JavaScript
// index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
// App.js
import React from "react";
import Test from "./Form/Test";

export default function App() {
  return <Test />;
}
// Form/Test.js
import React, { Component } from "react";
import Form from "./index";

export default class Test extends Component {
  render() {
    return (
      <div>
        <Form onSubmit={(datas) => {  console.log(datas); }} >
          <div>
            账号: <Form.Input name="loginId" />
          </div>
          <div>
            密码: <Form.Input name="loginPwd" type="password" />
          </div>
          <div>
            <Form.Button>提交</Form.Button>
          </div>
        </Form>
      </div>
    );
  }
}
// Form/formContext.js
import React from "react";

const ctx = React.createContext();

export const { Provider, Consumer } = ctx;

export default ctx;
// Form/index.js
import React, { Component } from "react";
import { Provider } from "./formContext";
import FormInput from "./FormInput";
import PropTypes from "prop-types";
import FormButton from "./FormButton";

export default class Form extends Component {
  state = {
    formData: {}, // 表单数据对象
    // 修改formData中的数据
    changeFormData: (name, val) => {
      this.setState({
        formData: {
          ...this.state.formData,
          [name]: val,
        },
      });
    },
    submit: () => {
      this.props.onSubmit && this.props.onSubmit(this.state.formData);
    },
  };

  static propTypes = {
    onSubmit: PropTypes.func,
  };

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

Form.Input = FormInput;
Form.Button = FormButton;
// Form/FormInput.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import ctx from "./formContext";

// 一定处于上下文中
export default class FormInput extends Component {
  static contextType = ctx;

  static defaultProps = {
    type: "text",
  };

  static propTypes = {
    name: PropTypes.string.isRequired, // 文本框的名称
    type: PropTypes.string.isRequired, // 文本框的类型
  };

  render() {
    return (
      <input
        value={this.context.formData[this.props.name] || ""}
        onChange={(e) => {
          this.context.changeFormData(this.props.name, e.target.value);
        }}
        type={this.props.type}
      />
    );
  }
}
// Form/FormButton.js
import React from "react";
import { Consumer } from "./formContext";

export default function FormButton(props) {
  return (
    <Consumer>
      {(ctx) => {
        return (
          <button onClick={() => { ctx.submit(); }}>
            {props.children}
          </button>
        );
      }}
    </Consumer>
  );
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Context 概念
  2. 2. Context 特点
  3. 3. 参数介绍
    1. 3.1. createContext
    2. 3.2. Provider
    3. 3.3. Consumer、contextType
  4. 4. 使用场景
  5. 5. 案例:表单