react 中的 connext

context 被译为上下文,在 react 中当你不想通过 props 或 state 逐层传递数据时,就可以使用 context 实现跨层级的组件数据传递。

如果使用 context ,需要两种组件,一个是 生产者 Provider ,通常是一个父组件;另一个是 context 的消费者,通常是一个或多个子组件,也就是说 context 是基于生产者消费者模式的。

对于父组件,需要通过一个静态属性 childContextTypes 声明提供给子组件的 context 对象属性,并实现一个实例 getChildContext 方法,返回一个代表 context 的纯对象。

import React from 'react'
import PropTypes from 'prop-types'

class MiddleComponent extends React.component {
    render (){
        return <ChildComponent />
    }
}

class ParentComponent extends React.Component {
    // 声明 context 对象属性
    static childContextTypes = {
        propA: propTypes.string,
        methods: propTypes.func
    }
    // 返回 context 对象函数,方法名是约定好的
    getChildContext(){
        return{
            propA: 'propA',
            methodA: () => 'methodA'
        }
    }
    render(){
        return <MiddleComponent />
    }
}

子组件通过以下方式访问父组件提供的 context:

import React from 'react';
import propTypes from 'prop-types';

class childComponent extends React.Component{
    // 声明需要使用的 context 属性
    static contextTypes = {
        propA: propTypes.string
    }
    
    render(){
        const { propA, methodA } = this.context;
        console.log(`context.propA = ${propA}`); // context.propA = propA;
        console.log(`context.methodA = ${methodA}`); // context.methodA = methodA;
        return ...
    }
}

子组件需要通过声明一个静态 contextTypes 后,才能访问父组件 context 对象的属性,否则即使属性名写的正确,拿到的对象也是 undefined。

而对于无状态子组件,可以通过如下方式访问父组件的 context:

import React from 'react';
import propTypes from 'prop-types';

const ChildComponent = (props, context) => {
    const { propA } = context;
    console.log(`context.propA = ${propA}`); // context.propA = propA;
    return ...
}
ChildComponent.contextProps = {
    propA: propTypes.string
}

在新版本中,更明确了生产者消费者模式的使用:

import React from 'react';
import ReactDom from 'react-dom';

const ThemeContext = React.createContext({
    background: 'red',
    color: 'green'
});

class App extends React.Component{
    render(){
        return(
            <ThemeContext.Provider value={background:'red',color:'green'}> // value 相当于 getChildContext()
                <Header />
            </ThemeContext.Provider>
        )
    }
}

通过 createContext 方法创建一个 Context 对象,包含两个组件:<Provider /> 和 <Consumer />,<Consumer /> 的 children 必须是一个函数,通过函数的参数获取<Provider /> 提供的 context:

<ThemeContext.Consumer>
    {context => (
        <h1 style={{background:context.background,color:context.color}}>
            {this.props.children}
        </h1>
    )}
</ThemeContext.Consumer>

可以直接获取 context 的地方

  • 构造方法中:constructor(props,context);
  • 生命周期中:componentWillReceiveProps(nextProps,nextContext); shouldComponentUpdate(nextProps,nextContext); componentWillUpdate(nextProps,nextContext);

对于面向函数的无状态组件,可以通过函数的参数直接访问组件的 Context:

const StatelessComponent = (props,context) =>{
    ...
}

缺点:react App 组件是树状结构,一层一层延伸,父子组件是一对多的线性依赖结构,随意的使用 context 会破坏这种线性依赖关系,导致产生组件之间一些不必要的额外依赖关系,降低组件的可复用性,破坏 App 的可维护性

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容