Skip to content

React Hooks系列(五)—— useContext #69

@LightXJ

Description

@LightXJ

useContext

新版 Context 常常有一个提供数据的生产者(Provider),和一个消费数据的消费者(Consumer),我们需要通过 Consumer 来以 render props 的形式获取到数据。如果从祖先组件传来了多个 Provider,那最终就又陷入了 render props 嵌套地狱。
image
useContext 允许我们以扁平化的形式获取到 Context 数据。即使有多个祖先组件使用多个 Context.Provider 传值,我们也可以扁平化获取到每一个 Context 数据。
image
再举一个例子,比较context的三种用法

// 创建一个 context
const Context = createContext(0)

// 组件一, Consumer 写法
class Item1 extends PureComponent {
  render () {
    return (
      <Context.Consumer>
        {
          (count) => (<div>{count}</div>)
        }
      </Context.Consumer>
    )
  }
}

// 组件二, contextType 写法
class Item2 extends PureComponent {
  static contextType = Context
  render () {
    const count = this.context
    return (
      <div>{count}</div>
    )
  }
}

// 组件三, useContext 写法
function Item3 () {
  const count = useContext(Context);
  return (
    <div>{ count }</div>
  )
}


function App () {
  const [ count, setCount ] = useState(0)
  return (
    <div>
      点击次数: { count } 
      <button onClick={() => { setCount(count + 1)}}>点我</button>
      <Context.Provider value={count}>
        <Item1></Item1>
        <Item2></Item2>
        <Item3></Item3>
      </Context.Provider>
    </div>
    )
}

说明:context 中的 Provider 和 Consumer,在类组件和函数组件中都能使用,contextType 只能在类组件中使用,因为它是类的静态属性
通过运行上面的例子,我们得到的结果是,三种写法都能够实现我们的需求,但是,三种写有各自的优缺点,下面为对比出的结果

写法 优缺点
consumer 嵌套复杂,Consumer 第一个子节点必须为一个函数,无形增加了工作量
contextType 只支持类组件,无法在多 context 的情况下使用
useContext 不需要嵌套,多 context 写法简单

通过上面的比较,没理由继续使用 consumer 和 contextType

useContex实现原理

function useContext(context) {
  return context._currentValue;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions