第一种 类&函数组件都可以使用

理解

一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信

注意

  1. 在应用开发中一般不用context, 一般都用它的封装react插件

使用

image.png
image.png
详细解析

1) 创建Context容器对象:
    const XxxContext = React.createContext()  

2) 渲染子组时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:
    <xxxContext.Provider value={数据}>
        子组件
  </xxxContext.Provider>

3) 后代组件读取数据:

    //第一种方式:仅适用于类组件 
      static contextType = xxxContext  // 声明接收context
      this.context // 读取context中的value数据

    //第二种方式: 函数组件与类组件都可以
      <xxxContext.Consumer>
        {
          value => ( // value就是context中的value数据
            要显示的内容
          )
        }
      </xxxContext.Consumer>

 4) 函数组件hook
   //父组件定义
    const xxxContext  = React.createContext() //创建context对象
    <xxxContext.Provider>
        {
          value => ()
        }
      </xxxContext.Provider>

    //子组件获取value
    const value = useContext(xxxContext)

案例代码

import React, { Component } from 'react'

//创建Context对象
const MyContext = React.createContext()
//结构出提供&消费数据两个组件
const {Provider,Consumer} = MyContext
//父组件
export default class A extends Component {

    state = {username:'tom',age:18}

    render() {
        const {username,age} = this.state
        return (
            <div className="parent">
                <h3>我是A组件</h3>
                <h4>我的用户名是:{username}</h4>

        //提供数据username,age
                <Provider value={{username,age}}>
                    <B/>
                </Provider>
            </div>
        )
    }
}
//子组件 不作为,为了演示祖孙组件通信
class B extends Component {
    render() {
        return (
            <div className="child">
                <h3>我是B组件</h3>
                <C/>
            </div>
        )
    }
}
//类组件 孙组件消费数据(演示第一种方式 只能在类组件中)
class C extends Component {
    //声明接收context
    static contextType = MyContext
    render() {
        const {username,age} = this.context
        return (
            <div className="grand">
                <h3>我是C组件</h3>
                <h4>我从A组件接收到的用户名:{username},年龄是{age}</h4>
            </div>
        )
    }
} 
//函数组件演示 孙组件消费数据(演示第二种方式 类|函数组件中都可以)
function C(){
    return (
        <div className="grand">
            <h3>我是C组件</h3>
            <h4>我从A组件接收到的用户名:
        //消费
            <Consumer>
                {value => `${value.username},年龄是${value.age}`}
            </Consumer>
            </h4>
        </div>
    )
}

第二种 类组件使用

注意 : childContextTypes 和 contextTypes 是不能省略的,跨级传值必须指定数据类型

实现步骤:
  1. 在父组件中,声明数据类型和值
     1.1 声明上下文数据类型
     static childContextTypes = {
       数据名: PropTypes.数据类型
     }
      1.2 向上下文控件中存值
      getChildContext(){
        return {
          数据: 值
        }
      }

    2. 在“无论哪一级别”子组件中,只需声明需要的全局上下文数据,就可自动注入子组件的context属性中
        static contextTypes = {
             数据名: 数据类型
        }
        或是:
        static contextTypes = {
             数据名: PropTypes.数据类型
        }

        在子组件中使用:
        {this.context.con}

父组件定义传递

import React,{Component} from 'react'
import PropTypes from 'prop-types'
import {Outlet} from 'react-router-dom'

export default class Cinema extends Component{
  static childContextTypes = {
    name:PropTypes.string,
    age:PropTypes.number
  }
  getChildContext(){
    return{
      name:'Dan',
      age:18
    }
  }
  render(){
    return(
      <div>Cinema</div>
    )
  }
}

子组件获取

import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class Nowplaying extends Component {
  static contextTypes = {
    name:PropTypes.string,
    age:PropTypes.number
  }
  render() {
    return (
      <div>{this.context.name}{this.context.age}</div>
    )
  }
}