5.Context

96 阅读2分钟

1.概念

Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。

Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。

因此context的使用场景就是:在组件树中,不同层级需要访问相同的数据源时,可以利用context,进行组件之间的通信

2.API

**React.createContext:**创建一个上下文的容器(组件), defaultValue可以设置共享的默认数据

const {Provider, Consumer} = React.createContext(defaultValue);

Provider(生产者): 和他的名字一样。用于生产共享数据的地方。生产什么呢? 那就看value定义的是什么了。value:放置共享的数据。

<Provider value={/*共享的数据*/}>
    /*里面可以渲染对应的内容*/
</Provider>

Consumer(消费者):这个可以理解为消费者。 他是专门消费供应商(Provider 上面提到的)产生数据。Consumer需要嵌套在生产者下面。才能通过回调的方式拿到共享的数据源。当然也可以单独使用,那就只能消费到上文提到的defaultValue

<Consumer>
  {value => /*根据上下文 进行渲染相应内容*/}
</Consumer>

3.demo

新建一份文件TopContext.js,创建一个context对象,用于存放不同子组件需要共同使用的数据源:

// TopContext.js 
import React from 'react'
export const TopContext = React.createContext({
    data: "default data"
})

注意,createContext中的参数并不是Provider的初始value,而是当没有提供Provider的时候,各个组件消费时的初始值。

然后,引入Top组件的时候用Provider包裹,通过value属性,将需要共享的数据源的值传入:

// app.js import { TopContext } from './TopContext.js'
class App extends React.Component {
    render() {
        return (
            <TopContext.Provider value={{ data: "source data" }}>
                <Top></Top>
            </TopContext.Provider>
        )
    }
}

然后在子组件中,我们就可以进行接收Provider提供的数据了,接收的方式有两种

1、利用contextType:

// context.js import { TopContext } from './TopContext'

class Bottom extends React.Component {
    render() {
        console.log("Bottom context: ", this.context)
        return (
            <div>
                <h3>Data in Bottom: { this.context.data }</h3>
            </div>
        )
    }
}
Bottom.contextType = TopContext

该属性用一个createContext构造的context对象赋值,赋值之后,组件内部的this.context属性就可以消费该context上的数据了

但是这个方式有个问题:只能订阅单一的context,因为contextType只能赋值一个context对象

所以我们可以用第二种方式

2、利用Consumer:

// context.js class Middle extends React.Component {
    render() {
        return (
            <TopContext.Consumer>
                {
                    value => {
                        console.log("value:", value)
                        return (
                            <div>
                                <h3>Data in Middle: { value.data }</h3>
                                <Bottom></Bottom>
                            </div>
                        )
                    }
                }
            </TopContext.Consumer>
        )
    }
}

利用对应context的Consumer,来消费对应context的数据

利用Consumer的内部的value,拿到context中的数据源,然后提供给我们的组件使用

4.useContext

// context.js import React, { useContext } from 'react'
const Middle = () => {
    const value = useContext(TopContext)
    return (
        <div>
            <h3>Data in Middle: {value.data}</h3>
            <Bottom></Bottom>
        </div>
    )
}

useContext实际上相当于Context.Consumer 或者 contextType = MyContext 的作用,用来订阅指定的context对象