useContext
新版 Context 常常有一个提供数据的生产者(Provider),和一个消费数据的消费者(Consumer),我们需要通过 Consumer 来以 render props 的形式获取到数据。如果从祖先组件传来了多个 Provider,那最终就又陷入了 render props 嵌套地狱。

useContext 允许我们以扁平化的形式获取到 Context 数据。即使有多个祖先组件使用多个 Context.Provider 传值,我们也可以扁平化获取到每一个 Context 数据。

再举一个例子,比较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;
}
useContext
新版 Context 常常有一个提供数据的生产者(Provider),和一个消费数据的消费者(Consumer),我们需要通过 Consumer 来以 render props 的形式获取到数据。如果从祖先组件传来了多个 Provider,那最终就又陷入了 render props 嵌套地狱。


useContext 允许我们以扁平化的形式获取到 Context 数据。即使有多个祖先组件使用多个 Context.Provider 传值,我们也可以扁平化获取到每一个 Context 数据。
再举一个例子,比较context的三种用法
说明:context 中的 Provider 和 Consumer,在类组件和函数组件中都能使用,contextType 只能在类组件中使用,因为它是类的静态属性
通过运行上面的例子,我们得到的结果是,三种写法都能够实现我们的需求,但是,三种写有各自的优缺点,下面为对比出的结果
通过上面的比较,没理由继续使用 consumer 和 contextType
useContex实现原理