React 跨层组件树传值-context上下文

  1. React 跨层组件树传值-context上下文
  2. 创建context
  3. 消费context
  4. default默认值
  5. 注意点

React 跨层组件树传值-context上下文

跨层组件树传值,可以使用context上下文来处理,先要定义一个上下文,然后在子孙组件中进行消费

详细文档查看React官网

创建context

首先需要创建一个context,可以给定一个默认值,当消费组件上没有Provider的时候,使用默认值。

然后通过上面的Provider指定想要传递的数据

colorCtx.js

import { createContext } from 'react'
export const ColorCtx = createContext("red")    

然后通过CTX.Provider 组件,绑定一个value,用来传递给子孙组件,这里我我们绑定一个{color: 'green'}状态

import React from 'react'
import Child from './Child'

import { ColorCtx } from './context'
class Parent extends React.Component {
    constructor(...props) {
        super(...props)
        this.state = {
            color: 'green'
        }
    }

    render() {
        return <>
            <ColorCtx.Provider value={this.state.color}>
                <p>Parent</p>
                <Child></Child>
            </ColorCtx.Provider>
        </>
    }
}

export default Parent

消费context

下面我们就可以在子孙组件里面消费绑定的value了,有以下几种方式可以消费

  • 使用consumer消费

    在使用consumer的时候,不能在生命周期中获取到上下文的信息,只能在consumer里面获取到,同时如果需要同时消费多个Provider,也只能使用consumer消费

    import React from 'react'
    import { ColorCtx } from './context'
    
    class Child extends React.Component {
        constructor(...props) {
            super(...props)
        }
    
        render() {
            return <>
                <ColorCtx.Consumer>
                    {value => <div>
                        <p style={{color: value}}>Child</p>
                    </div>}
                </ColorCtx.Consumer>
            </>
        }
    }
    
    export default Child
    
  • 使用静态方法contentType消费

    通过指定contentType,来消费Provider,取值的时候就可以使用this.context取值

    import React from 'react'
    import { ColorCtx } from './context'
    
    class Child extends React.Component {
        constructor(...props) {
            super(...props)
            this.state = {
                color: 'green'
            }
        }
    
        // 定义了这个,会把this.context 映射到 vlue
        static contextType = ColorCtx
    
        render() {
            return <>
                <div>
                    <p style={{color: this.context}}>Child</p>
                </div>
            </>
        }
    }
    
    //上面的 static contextType = ColorCtx 也可以使用这种方法指定
    // Child.contextType = ColorCtx
    
    export default Child
    
  • 消费多个Provider

    1. 创建多个context
    import {createContext} from 'react'
    export const ColorCtx = createContext('red')
    export const BackColorCtx = createContext('white')
    
    1. 在父组件中提供多个Provider
    import React from 'react'
    import Child from './Child'
    import { ColorCtx, BackColorCtx } from './context'
    
    class Parent extends React.Component {
        constructor(...props) {
            super(...props)
            this.state = {
                color: 'green',
                backColor: 'black'
            }
        }
    
        render() {
            return <>
                <ColorCtx.Provider value={this.state.color}>
                    <BackColorCtx.Provider value={this.state.backColor}>
                        <p>Parent</p>
                        <Child></Child>
                    </BackColorCtx.Provider>
                </ColorCtx.Provider>
            </>
        }
    }
    
    export default Parent
    
    1. 在子孙组件中进行消费
    import React from 'react'
    import { ColorCtx, BackColorCtx } from './context'
    
    class Child extends React.Component {
        constructor(...props) {
            super(...props)
        }
    
        render() {
            return <>
                <ColorCtx.Consumer>
                    { color => 
                        <BackColorCtx.Consumer>
                            { backColor => 
                                <div>
                                    <p style={{color: color, backgroundColor: backColor}}>Child</p>
                                </div>
                            }
                        </BackColorCtx.Consumer>
                    }
                </ColorCtx.Consumer>
            </>
        }
    }
    
    export default Child
    

default默认值

如果说子孙组件没有提供Provider,则子组件的消费者的value会被赋予默认值。

例如第二个子组件Child没有提供Provider,则Child会被渲染成红色,就是上面export const ColorCtx = createContext('red')指定的

class Parent extends React.Component {
    constructor(...props) {
        super(...props)
        this.state = {
            color: 'green',
            backColor: 'black'
        }
    }

    render() {
        return <>
            <ColorCtx.Provider value={this.state.color}>
                <p>Parent</p>
                <Child></Child>
            </ColorCtx.Provider>
            <Child></Child>
        </>
    }
}

注意点

contextvalue发生变化的时候,会引发子组件的更新,在React内部,很暴力,直接使用===进行对比新旧值,那如果我们使用类似<ColorCtx.Provider value={{someValue: 'value'}}>的方式传递value,内部比较直接{someValue: 'value'} === {someValue: 'value'},此时永远都是false,子组件就会更新,造成性能问题,我们的解决方法是把value放到state中,传递的是state里的值,就像上述例子里那样,这样的话,值没变子组件就不会更新了。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com