React 中 useContext 的基本使用和原理解析

React 中 useContext 的使用方法
在 React 中,useContext 是一个内置的 Hook,用于在函数组件中轻松访问 Context(全局公共状态),避免了手动逐层传递 props 的复杂性。它依赖于 Context API,通过 Provider 提供数据,后代组件通过 useContext 消费数据。以下是详细的使用方法和步骤,基于 React 官方指南和实践经验。
1. 创建 Context 对象
首先需要使用 React.createContext 创建一个 Context 对象。这个对象包含 Provider 和 Consumer 组件,但 useContext 简化了消费过程。
defaultValue是当组件上方无 Provider 时的回退值,通常设为null或初始状态。
2. 使用 Provider 提供数据
在父组件中,用 `` 包裹子组件,并通过 value 属性传递数据。Provider 必须位于调用 useContext 的组件之上。
注意:Provider 的
value变化时,所有消费该 Context 的组件会自动重新渲染。
3. 在后代组件中使用 useContext 消费数据
在后代组件中,导入 Context 对象并调用 useContext,直接获取 Provider 提供的 value。
关键点:
useContext(MyContext)返回最近的 Provider 的value;若无 Provider,则返回defaultValue。代码简洁,无需嵌套 ``。
Context 变化时,React 会触发组件重新渲染,确保数据最新。
4. 完整代码示例
整合以上步骤,一个简单应用:
在类组建中,useContext 的使用方法
在类组件中使用 Context 有两种方式:
使用
static contextType属性(只能订阅单一 Context)使用
Context.Consumer(可订阅多个 Context)
而在函数组件中,我们使用 useContext 钩子(可订阅多个 Context)。
下面我将详细说明类组件中使用 Context 的方法,并对比函数组件中的使用差异。
1、使用 static contextType(单一 Context 订阅)
步骤:
创建 Context:
const MyContext = React.createContext(defaultValue);在类组件中通过
static contextType = MyContext;指定要订阅的 Context通过
this.context访问 Context 的值
示例代码
2、使用 Context.Consumer(支持多个 Context)
步骤:
在类组件的
render方法中,使用 `` 组件包裹内部使用函数作为子元素(render prop 模式)
示例代码:
类组件与函数组件使用 Context 的主要区别
useContext 实现原理详解
useContext 的实现原理基于 React 的 上下文机制(Context) 和 订阅-发布模式,主要涉及三个核心环节:
1. Context 对象的内部结构
每个通过 createContext() 创建的 Context 对象包含以下关键属性:
核心是 _currentValue (存储当前值) 和 _subscribe (管理订阅者链表)
2. 值读取与订阅机制
当调用 useContext(MyContext) 时:
currentlyRenderingFiber 是 React 内部的一个全局变量,用于指向当前正在执行的函数组件所对应的 Fiber 节点。它的主要作用是在函数组件渲染过程中为 Hooks 提供访问当前组件状态的桥梁。
具体过程:
读取值:直接访问
Context._currentValue获取最新值建立订阅:将当前函数组件对应的 Fiber 节点添加到 Context 的订阅者链表
通过
currentlyRenderingFiber.dependencies链表维护订阅关系每个依赖项包含
context指针和订阅状态
3. 更新触发流程
当 Provider 的值更新时:
关键点:
批量更新:React 会合并多个 Context 更新,避免频繁渲染
精准更新:只更新订阅该 Context 的组件(通过 Fiber 依赖链)
默认值处理:无 Provider 时返回
createContext(defaultValue)的默认值
版权声明: 本文为 InfoQ 作者【老李说技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/b8abbf70cb2e6a982af94c764】。文章转载请联系作者。







评论