React之Context

旧版

  • Context三步曲
    • 【1】父组件中定义childContextTypes上下文对象的属性类型
    class Father extends React.Component {
        static childContextTypes = {
            name:PropTypes.string,
            age:PropTypes.number,
            color:PropTypes.string,
            setColor:PropTypes.func
        }
        render(){
            return(
                <>
                 <Son/>
                </>
            );
        }
    }
    复制代码
    • 【2】父组件中定义getChildContext函数返回真正的上下文对象
    class Father extends React.Component {
        ...
        constructor(){
            super();
            this.state = {
                color:'red'
            }
        }
        getChildContext(){
            return {
                name:'GuYan',
                age:'18',
                color:this.state.color,
                setColor:this.setColor
            }
        }
        ...
        setColor = (color) =>{
            this.setState({
                color:color
            })
        }
    }
    复制代码
    • 【3】子组件中定义contextTypes接收上下文对象的属性类型
    class Son extends React.Component{
        static contextTypes = {
            color:PropTypes.string,
            setColor:PropTypes.func,
            name:PropTypes.name
        }
        render(){
            return (
               <>
                 <p style={{color:this.context.color}}>{this.context.name}</p>
                 <button onClick={()=>{this.context.setColor('red')}}>
                 Change Color To Red
                 </button>
                 <button onClick={()=>{this.context.setColor('green')}}>
                 Change Color To Green
                 </button>
               </>
            )
        }
        
    }
    复制代码

新版

类组件

  • Context三步曲
    • 【1】全局通过React.creactContext()创建ThemeContext对象
    import React, { Component } from 'react';
    const ThemeContext = React.createContext();
    复制代码
    • 【2】父组件中通过ThemeContext.Provider组件包裹,并在此组件的value属性上定义上下文对象
    class Father extends Component{
        constructor(props){
            super(props);
            this.state = {
                color:'red',
                name:'GuYan',
            }
        }
        render(){
            const contextValue = {
                color:this.state.color,
                setColor:this.setColor,
                name:this.state.name
            }
            return (
                <Theme.Provider value = {contextValue}>
                    <Son/>
                </Theme.Provider>
            )
        }
        setColor = (color) =>{
            this.setColor({
                color:color
            })
        }
    }
    复制代码
    • 【3】子组件中通过定义contextType属性对象为ThemeContext对象来接收上下文对象
    class Son extends Component {
        static contextType = ThemeContext;
        render(){
            return (
                <>
                 <p style={{color:this.context.color}}>{this.context.name}</p>
                 <button onClick={()=>{this.context.setColor('red')}}>
                 Change Color To Red
                 </button>
                 <button onClick={()=>{this.context.setColor('green')}}>
                 Change Color To Green
                 </button>
               </>
            )
        }
    }
    复制代码

函数组件

  • Context三步曲
    • 【1】全局通过React.createContext()创建ThemeContext对象
    import React, {Component} from 'react';
    const ThemeContext = React.createContext();
    复制代码
    • 【2】父组件通过ThemeContext.Provider组件包裹,并在此组件的value属性上定义上下文对象
    class Father extends Component {
        constructor(props){
            super(props);
            this.state = {
                name:'GuYan',
                color:'red'
            }
        }
        render(){
            const contextValue = {
                name:this.state.name,
                color:this.state.color
            }
            return (
                <ThemeContext.Provider value = {contextValue}>
                    <Son/>
                </ThemeContext.Provider>
            )
        }
        setColor = (color) =>{
            this.setColor({
                color:color
            })
        }
    }
    复制代码
    • 【3】子组件通过ThemeContext.Consumer组件包裹,需要注意的是这里需要在内部包裹一个匿名函数组件的形式
    function Son(){
        return (
            <ThemeContext.Consumer>
                {
                    value=>(
                        <>
                            <p style={{color:value.color}}>{value.name}</p>
                            <button onClick={()=>{value.setColor('red')}}>Change Color To Red</button>
                            <button onClick={()=>{value.setColor('green')}}>Change Color To Green</button>
                            <GrandSon/>
                        </>
                    )
                }
            </ThemeContext.Consumer>
        )
    }
    复制代码
    function GrandSon(){
        return (
            <ThemeContext.Consumer>
                {
                    value=>(
                        <p style={{color:value.color}}>name:{value.name}</p>
                    )
                }
            </ThemeContext.Consumer>
        )
    }
    复制代码

原理

  • 控制台输出ThemeContext对象,结果如下
  • 由上图我们可以看出ThemeContext对象中比较重要的三个属性,也就是说React.createContext()执行返回比较重要的三个属性
    • 【1】$$typeof
    • 【2】Provider
    • 【3】Consumer
  • 源码实现
import React,{Component} from 'react';
function myCreateContext(){
    const $$typeof = Symbol.for('react.context');
    class Provider extends Component{
        static value;
        static $$typeof = Symbol.for('react.provider');
        constructor(props){
            super(props);
            Provider.value = props.value;
            this.state = {
                value:props.value;
            }
        }
        static getDerivedStateFromProps(nextProps,prevState){
            Provider.value = nextProps.value;
            return {value:nextProps.value};
        }
        render(){
            return this.props.children;
        }
    }
    class Consumer extends Component{
        static $$typeof = Symbol.for('react.consumer');
        render(){
            return this.props.children(Provider.value);
        }
    }
    return {
        $$typeof,
        Provider,
        Consumer
    }
}
复制代码

转载于:https://juejin.im/post/5cd82cf951882569584433f6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值