学习React Hooks系列 - useContext

3,492 阅读3分钟

最近在学习React-Hooks,顺便记一下笔记,有错误之处还请指正,共勉。

Context 

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

React组件中,数据是通过 props 属性自上而下(由父及子)进行传递的:


当一些数据需要全局用到的业务场景下:例如切换用户登录信息、切换语言、切换主题,props层层传递数据就显得复杂繁琐。Context提供了一种共享数据的方式,不用通过props层层传递数据,在任意一级组件中都可以直接获取到需要的数据。


创建一个Context对象

import React, { useState, createContext } from 'react';
const CountContext = createContext();

每个 Context 对象都会返回一个 Provider React 组件,并接收一个value值,传递给Consumer组件。

<Consumer>没有对应的Provider传值,则使用createContext(defaultValue)默认值。

创建一个函数组件App和一个类组件子组件Child

import React, { Component, useState, createContext } from 'react';
const CountContext = createContext();
function App() {
    const [count, setCount] = useState(0);
    return (
        <div>
            <button
                type='button'
                onClick={() => {
                    setCount(count + 1)
                }}
            >
                addCount:{count}
            </button>
            <CountContext.Provider value={count}>
                <Child />
            </CountContext.Provider>
        </div>
    )
}

class Child extends Component {
    render() {
        return(
            <CountContext.Consumer>
                { count => <h1>count: { count }</h1> }
            </CountContext.Consumer>
        )
    }
}
export default App;

执行程序,点击按钮,0会自增加1。显示addCount:1  count: 1


使用contextType属性

官网中的解释:挂载在 class 上的 ContextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

class Child extends Component {
    render() {
        return(
            <CountContext.Consumer>
                { count => <h1>count: { count }</h1> }
            </CountContext.Consumer>
        )
    }
}

// 修改为以下代码:
class Child extends Component {
    const contextType = CountContext;
    render() {
        const count = this.context;
        return(
            <h1>count: { count }</h1>
        )
    }
}

使用useContext

import React, { Component, useState, createContext, useContext } from 'react';
function Child() {
    const count = useContext(CountContext);
    reutrn(
        <h1>count:{count}</h1>
    )
}

当组件上层最近的 <Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给Provider Context的value 值。

useContext 的参数必须是CContext 对象本身。

Consumer、ContextType、useContext的区别

Consumer组件在类组件和函数组件中都可以使用,作为消费组件,可以有多个Provider传值,接收多个全局变量。

ContextType属性作为类静态成员,在函数组件中无法使用ContextType会被重赋值为一个新的Context对象,ContextType只能使用一个Context,就算有多个Provider传值,也只会接收一个值。

useContext是函数组件中的方法,可以有多个Provider传值,接收多个全局变量,useContext解决了Consumer组件书写繁琐的问题,还解决了ContextType只能使用一个Context的问题。

不要只是为了避免在几个层级下的组件传递 props 而使用Context,它是被用于在多个层级的多个组件需要访问相同数据的场景。

不要滥用Context,会破坏组件的独立性