当前位置: 首页 > news >正文

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

React 中 useContext 的使用方法

在 React 中,useContext 是一个内置的 Hook,用于在函数组件中轻松访问 Context(全局公共状态),避免了手动逐层传递 props 的复杂性。它依赖于 Context API,通过 Provider 提供数据,后代组件通过 useContext 消费数据。以下是详细的使用方法和步骤,基于 React 官方指南和实践经验。

1. 创建 Context 对象

首先需要使用 React.createContext 创建一个 Context 对象。这个对象包含 ProviderConsumer 组件,但 useContext 简化了消费过程。

import React from 'react';
// 创建Context,可设置默认值(可选)
const MyContext = React.createContext(defaultValue);
  • defaultValue 是当组件上方无 Provider 时的回退值,通常设为 null 或初始状态。
2. 使用 Provider 提供数据

在父组件中,用 <Context.Provider> 包裹子组件,并通过 value 属性传递数据。Provider 必须位于调用 useContext 的组件之上。

import React from 'react';
import ChildComponent from './ChildComponent';
import MyContext from './MyContext';function ParentComponent() {const sharedData = { theme: 'dark', user: 'Alice' }; // 共享数据return (<MyContext.Provider value={sharedData}><ChildComponent /> {/* 后代组件可访问sharedData */}</MyContext.Provider>);
}
  • 注意​:Provider 的 value 变化时,所有消费该 Context 的组件会自动重新渲染​​。
3. 在后代组件中使用 useContext 消费数据

在后代组件中,导入 Context 对象并调用 useContext,直接获取 Provider 提供的 value

import React, { useContext } from 'react';
import MyContext from './MyContext'; // 导入父组件中的Contextfunction ChildComponent() {const publicData = useContext(MyContext); // 调用useContext获取数据return (<div><p>当前主题: {publicData.theme}</p>{/* 示例:渲染图片或其他UI */}<img src="image-path" alt="示例" style={{ width: '50px', marginLeft: '10px' }} /></div>);
}
  • 关键点​:
    • useContext(MyContext) 返回最近的 Provider 的 value;若无 Provider,则返回 defaultValue
    • 代码简洁,无需嵌套 <Context.Consumer>
    • Context 变化时,React 会触发组件重新渲染,确保数据最新​​。
4. 完整代码示例

整合以上步骤,一个简单应用:

// 文件: Context.js
import React from 'react';
export const ThemeContext = React.createContext({ theme: 'light' });// 文件: App.js (父组件)
import React from 'react';
import { ThemeContext } from './Context';
import Child from './Child';function App() {return (<ThemeContext.Provider value={{ theme: 'dark' }}><Child /></ThemeContext.Provider>);
}// 文件: Child.js (后代组件)
import React, { useContext } from 'react';
import { ThemeContext } from './Context';function Child() {const { theme } = useContext(ThemeContext);return <div>当前主题: {theme}</div>; // 输出: 当前主题: dark
}

在类组建中,useContext 的使用方法

在类组件中使用 Context 有两种方式:

  1. 使用 static contextType 属性(只能订阅单一 Context)
  2. 使用 Context.Consumer(可订阅多个 Context)

而在函数组件中,我们使用 useContext 钩子(可订阅多个 Context)。

下面我将详细说明类组件中使用 Context 的方法,并对比函数组件中的使用差异。

1、使用 static contextType(单一 Context 订阅)

步骤:

  • 创建 Context:const MyContext = React.createContext(defaultValue);
  • 在类组件中通过 static contextType = MyContext; 指定要订阅的 Context
  • 通过 this.context 访问 Context 的值

示例代码

import React from 'react';// 创建Context
const ThemeContext = React.createContext('light');class MyClassComponent extends React.Component {static contextType = ThemeContext; // 关键:静态属性赋值render() {const theme = this.context; // 通过this.context访问return <div>当前主题: {theme}</div>;}
}// 在父组件中提供Context
function App() {return (<ThemeContext.Provider value="dark"><MyClassComponent /></ThemeContext.Provider>);
}
2、使用 Context.Consumer(支持多个 Context)

步骤:

  • 在类组件的 render 方法中,使用 <MyContext.Consumer> 组件包裹
  • 内部使用函数作为子元素(render prop 模式)

示例代码:

import React from 'react';// 创建两个Context
const ThemeContext = React.createContext('light');
const UserContext = React.createContext('Guest');class MyClassComponent extends React.Component {render() {return (// 消费多个Context<ThemeContext.Consumer>{theme => (<UserContext.Consumer>{user => (<div>主题: {theme}, 用户: {user}</div>)}</UserContext.Consumer>)}</ThemeContext.Consumer>);}
}// 在父组件中提供多个Context
function App() {return (<ThemeContext.Provider value="dark"><UserContext.Provider value="Alice"><MyClassComponent /></UserContext.Provider></ThemeContext.Provider>);
}

3、类组件与函数组件使用 Context 的主要区别

特性类组件函数组件
订阅方式1. static contextType + this.context(单一)2. Context.Consumer(支持多个)useContext 钩子(支持多个)
多个 Context 使用使用 Context.Consumer 嵌套较深直接多次调用 useContext,简洁清晰
代码简洁性相对冗长,尤其是多个 Context 时非常简洁
组件类型限制static contextType 仅适用于类组件(引用[1])useContext 仅适用于函数组件
动态更新当 Context 更新时,组件都会重新渲染同样重新渲染,但可通过 React.memo 优化

4、useContext 实现原理详解

useContext 的实现原理基于 React 的 上下文机制(Context) 和 ​订阅-发布模式​,主要涉及三个核心环节:

1. Context 对象的内部结构

每个通过 createContext() 创建的 Context 对象包含以下关键属性:

const MyContext = React.createContext(defaultValue);
// 内部结构:
{_currentValue: defaultValue,  // 当前值存储_threaded: true,             // 标识当前渲染线程Provider: { ... },           // Provider 组件Consumer: { ... },           // Consumer 组件_currentRenderer: null,      // 当前渲染器_globalName: null,           // 全局名称_subscribe: function() { ... } // 订阅函数
}

核心是 _currentValue (存储当前值) 和 _subscribe (管理订阅者链表)

2. 值读取与订阅机制

当调用 useContext(MyContext) 时:

function useContext(Context) {// 1. 从 Context._currentValue 读取当前值const value = readContext(Context); // 2. 将当前组件添加到订阅链表subscribeToContext(Context, currentlyRenderingFiber);return value; // 返回上下文值
}

currentlyRenderingFiber 是 React 内部的一个​全局变量​,用于指向当前正在执行的函数组件所对应的 ​Fiber 节点​。它的主要作用是在函数组件渲染过程中为 Hooks 提供访问当前组件状态的桥梁。

具体过程:

  1. 读取值​:直接访问 Context._currentValue 获取最新值
  2. 建立订阅​:将当前函数组件对应的 Fiber 节点添加到 Context 的订阅者链表
    • 通过 currentlyRenderingFiber.dependencies 链表维护订阅关系
    • 每个依赖项包含 context 指针和订阅状态
3. 更新触发流程

当 Provider 的值更新时:

<MyContext.Provider value={newValue}>
// 1. 更新 Context._currentValue = newValue
// 2. 遍历订阅者链表 (Context._subscribe)
// 3. 标记所有订阅组件的 Fiber 节点为需要更新
// 4. 触发重新渲染

关键点:

  • 批量更新​:React 会合并多个 Context 更新,避免频繁渲染
  • 精准更新​:只更新订阅该 Context 的组件(通过 Fiber 依赖链)
  • 默认值处理​:无 Provider 时返回 createContext(defaultValue) 的默认值
http://www.dtcms.com/a/564696.html

相关文章:

  • 重庆网站建设公司是什么意思可信赖的做网站
  • 【js逆向案例四】小红书
  • Next.js路由系统
  • 6、webgl 基本概念 + 四边形纹理
  • 【weblogic】XML反序列化漏洞
  • 20-控制流多次异步
  • Python Seaborn详解:让数据可视化更简单、更美观的利器
  • 基于c 的网站开发河北邢台路桥建设公司网站
  • VivaCut 4.4.0 | 专业的视频剪辑编辑制作工具,有非常多的特效,可替代剪映
  • CY5-α-酮戊二酸,(CY5-α-Ketoglutarate, CY5-α-KG)
  • Matlab模拟对流方程迎风格式验证
  • LeetCode 面试经典 150_二叉树_相同的树(68_100_C++_简单)(DFS)
  • LeetCode算法日记 - Day 91: 最长数对链
  • 潍坊哪个网站建设公司好wordpress刷新才显示
  • 在 Hive 中NULL的理解
  • 如何让UE5的插件Ultra Dynamic Sky的光照对齐真实时间?
  • 【问题解决】用pnpm创建的 Vue3项目找不到 .eslintrc.js文件 及 后续的eslint配置的解决办法
  • Kubernetes Pod 基本原理:全面详解
  • 有关于cnb自动化的脚本补全
  • Hive三大连接操作全解析
  • css3新增过渡
  • Hive 中的 COALESCE 函数作用
  • 网站建设内部下单流程图赣州的免费网站建设
  • 广东顺德网站建设instagram wordpress
  • Linux连接Doris:MySQL与Beeline指南
  • 【金仓数据库】ksql 指南(四) —— 创建与管理表(KingbaseES 数据存储核心)
  • Swift项目生成Framework流程以及与OC的区别
  • C++多线程同步与互斥
  • Python Jupyter Notebook 完全指南:从入门到精通
  • 站点查询wordpress 外贸网站