首页
学习
活动
专区
圈层
工具
发布

React

修改于 2026-06-23 10:49:56
3
概述

React(又称 React.js)是由 Meta(原 Facebook)团队开发并维护的开源前端 JavaScript 库,用于构建用户界面,尤其擅长单页应用(SPA)和复杂交互场景。React 采用声明式编程范式,让开发者通过组件(Component)组合来构建 UI,当数据变化时自动更新界面。自 2013 年开源以来,React 已成为全球使用最广泛的前端框架之一,拥有庞大的社区生态和企业级应用案例。

一、React 的工作原理是什么?Virtual DOM 是如何工作的?

1. 核心工作原理

React 的核心思想是:当应用状态(State)发生变化时,框架自动计算出界面需要更新的最小范围,然后只更新那一部分真实 DOM。这套机制由 Virtual DOM(虚拟 DOM)和协调算法(Reconciliation)共同完成。

2. Virtual DOM 的工作流程

  • 初始渲染:React 根据 JSX 组件树,在内存中构建一棵轻量级的 JavaScript 对象树(即 Virtual DOM 树)
  • 状态变化触发更新:当组件状态或属性(Props)发生变化时,React 基于新数据生成一棵新的 Virtual DOM 树
  • Diff 比对(协调过程):React 将新树与上一轮渲染的树进行比对,找出差异点。该算法时间复杂度为 O(n),通过元素类型、key 属性和位置信息进行启发式比对,避免全量比较
  • 提交阶段(Commit Phase):React 将比对出的差异一次性批量更新到真实 DOM 中,只修改发生变化的具体节点,未变化的部分保持不变

3. Fiber 架构的改进

React 16 引入的 Fiber 架构将协调过程重构为可中断的链表结构,使渲染过程可以被优先级更高的任务(如用户输入)打断,从而提升交互响应速度。React 18/19 在此基础上进一步增强了并发渲染能力,支持时间切片(Time Slicing)和过渡更新(Transitions)。

二、React 组件有哪几种定义方式?函数组件和类组件有什么区别?

1. 函数组件(Function Component)

函数组件是最基础也是当前最推荐的组件定义方式,本质是一个接收 Props 并返回 JSX 的普通 JavaScript 函数。React 16.8 引入 Hooks 后,函数组件已能完全替代类组件的所有功能,包括状态管理和副作用处理。

2. 类组件(Class Component)

类组件通过 ES6 class 语法继承 React.Component 来定义,必须实现 render() 方法返回 JSX。类组件中通过 this.statethis.setState() 管理状态,通过生命周期方法(如 componentDidMountcomponentDidUpdate)处理副作用。

3. 核心区别对比

  • 语法结构:函数组件是普通函数,无 this 指向问题;类组件需要 constructor 绑定和 this 处理,容易出现绑定错误
  • 状态管理:函数组件使用 useStateuseReducer 等 Hooks;类组件使用 this.statethis.setState()
  • 副作用处理:函数组件使用 useEffect 统一处理挂载、更新和卸载逻辑;类组件分散在 componentDidMountcomponentDidUpdatecomponentWillUnmount 等方法中
  • 性能开销:函数组件无实例创建开销,打包体积更小,更容易被 Tree-shaking 优化

4. 当前推荐方案

React 官方和社区在2026 年的一致推荐是:所有新代码使用函数组件 + Hooks。类组件不会被移除,仍可用于维护旧项目,但新功能开发应优先采用函数组件方案。

三、React Hooks 是什么?常用的 Hooks 有哪些?

1. Hooks 的核心概念

React Hooks 于 React 16.8(2019 年)正式引入,允许在函数组件中使用状态和其他 React 特性,而无需编写类组件。Hooks 的本质是一些特殊的函数,它们让你"钩入"(Hook into)React 的状态管理和生命周期能力。

2. 基础必用 Hooks

  • useState:为函数组件添加局部状态,返回当前状态值和更新函数。支持函数式更新(依赖上一次状态值)和惰性初始化(避免每次渲染重复计算)
  • useEffect:处理副作用,替代类组件的生命周期方法。通过依赖数组控制执行时机:空数组等价于 componentDidMount,无依赖数组则在每次渲染后执行,指定依赖则在依赖变化时执行
  • useContext:读取 React Context 的值,解决 Props 深层透传(Prop Drilling)问题
  • useReducer:适用于复杂状态逻辑,工作方式类似 Redux,通过 dispatch 发送 action 由 reducer 函数计算新状态

3. 性能优化 Hooks

  • useMemo:缓存计算结果,避免每次渲染都执行昂贵的计算。仅在依赖项变化时重新计算
  • useCallback:缓存函数引用,避免每次渲染都创建新的函数实例,配合 React.memo 使用可防止子组件不必要重渲染
  • useMemo 和 useCallback 应基于性能分析结果有选择地使用,而非默认包裹所有函数和计算结果

4. 引用与 ID 类 Hooks

  • useRef:返回一个在组件整个生命周期内持续存在的可变对象,常用于访问 DOM 元素、存储定时器 ID 或上一次渲染的值
  • useId:生成跨服务端和客户端渲染一致的全局唯一 ID,主要用于无障碍访问(Accessibility)场景中的表单标签关联

5. React 18/19 新增 Hooks

  • useTransition:将状态更新标记为非紧急,保持 UI 交互响应(如搜索输入时的标签页切换)
  • useDeferredValue:延迟更新某个值,类似防抖但由 React 渲染管道原生支持
  • useOptimistic(React 19+):在服务器确认之前立即显示乐观更新结果,自动在请求失败时回滚
  • useActionState(React 19+):简化表单状态管理,自动处理 pending 状态、错误和乐观更新
  • use()(React 19+):读取 Promise 或 Context 的值,可在条件语句和循环内调用(不受 Hooks 规则约束),与 Suspense 和 Error Boundary 集成,是 useContext 的增强替代方案

四、React 的生命周期方法有哪些?在函数组件中如何替代?

1. 类组件生命周期三个阶段

  • 挂载阶段(Mounting)constructor 初始化状态 → render 渲染 → componentDidMount 挂载完成(适合发起网络请求、绑定订阅)
  • 更新阶段(Updating)shouldComponentUpdate 决定是否重渲染 → render 重新渲染 → componentDidUpdate 更新完成
  • 卸载阶段(Unmounting)componentWillUnmount 清理定时器、取消订阅、移除事件监听

2. useEffect 对生命周期的替代方案

类组件生命周期

函数组件 Hooks 替代方案

constructor 初始化状态

useState 初始化状态

componentDidMount

useEffect 依赖数组为空 []

componentDidUpdate

useEffect 带依赖数组 [dep]

componentWillUnmount

useEffect 返回清理函数 return () => {...}

shouldComponentUpdate

React.memo 或 useMemo

3. 无法被 Hooks 替代的生命周期

  • getSnapshotBeforeUpdate:在 DOM 更新前同步读取布局信息(如滚动位置),Hooks 无法实现同等能力
  • componentDidCatch / getDerivedStateFromError:错误边界(Error Boundary)功能,React 官方明确说明仅类组件支持,Hooks 无对应 API

4. 实际开发建议

新项目应统一使用函数组件 + useEffect 模式。useEffect 的优势在于可以将"挂载时执行 + 更新时执行 + 卸载时清理"的逻辑整合在同一个函数中,避免类组件中生命周期方法分散的问题。

五、React 的状态管理有哪些方案?Redux、MobX、Zustand 各有什么特点?

1. 状态管理方案分类

React 状态管理可分为多层次方案:组件局部状态(useState / useReducer)、跨组件状态(Context API)、以及独立的全局状态管理库(Redux、Zustand、MobX、Recoil 等)。选择取决于应用规模、团队经验和状态更新频率。

2. Redux Toolkit

  • 定位:最成熟、生态最丰富的全局状态管理方案,由 Redux 团队维护
  • 体积:体量适中(含 Redux Toolkit 核心)
  • 特点:单向数据流、纯函数 Reducer、可预测的状态变更;Redux Toolkit 相比传统 Redux 大幅减少样板代码
  • 优势:Redux DevTools 支持时间旅行调试、Action 重放、状态差异对比,是企业级调试的首选
  • 适用场景:大型企业应用、需要调试追溯和多团队协作的项目、已使用 RTK Query 处理数据请求的场景

3. Zustand

  • 定位:轻量级、最小化 API 的状态管理库,由 Poimandres 集体维护
  • 体积:约 2.1KB(gzip 后),属于轻量级状态管理库
  • 特点:基于 Hook 的简洁 API,无需 Provider 嵌套,直接通过 useStore 订阅状态;支持中间件(persist 持久化、devtools 调试、immer 不可变更新)
  • 优势:学习成本极低(约 15 分钟即可上手),性能优秀,与 Next.js 服务器组件完全兼容
  • 适用场景:中小型应用、快速迭代的创业团队、对包体积敏感的性能敏感型应用

4. MobX

  • 定位:基于响应式编程(Reactive Programming)的状态管理库
  • 体积:体量适中(gzip 后)
  • 特点:可观察状态(Observable State)+ 自动依赖追踪,状态变更后自动更新依赖该状态的组件,无需手动配置选择器
  • 优势:细粒度更新(只重新渲染真正变化的组件),书写风格接近原生 JavaScript 可变对象操作
  • 限制:与 Next.js 服务器组件不兼容(可观察代理假设单一长生命周期 JavaScript 上下文);TypeScript 支持需要手动类型标注
  • 适用场景:具有复杂字段联动的表单系统、配置型应用、团队有响应式编程经验的场景

5. 选型决策参考

2026 年的社区趋势是:新项目首选 Zustand(兼顾性能和开发效率);大型企业项目或有强调试需求时选择 Redux Toolkit;复杂表单/配置场景可考虑 MobX;纯服务端状态优先使用 TanStack Query(React Query)而非上述客户端状态库。

六、React Router 是如何工作的?如何实现路由守卫?

1. React Router 的核心工作原理

React Router 是一个基于 React 的多策略路由器,通过 History API 拦截浏览器导航行为,在客户端完成路由切换和组件渲染,无需向服务器发起整页请求。当用户点击 <Link> 组件时,React Router 阻止默认的页面跳转行为,更新 URL,并根据当前 URL 匹配对应的 <Route> 组件进行渲染。

2. 动态路由参数

React Router 通过 :paramName 语法支持动态路由段,在组件内通过 useParams() Hook 读取参数值。useSearchParams() 提供对 URL 查询字符串的读写能力,类似 useState 的 API 设计。

3. 嵌套路由(Nested Routes)

嵌套路由是 React Router 的核心特性,允许子路由在父路由的布局组件(Layout)内部渲染。父组件通过 <Outlet /> 组件指定子路由的渲染位置,实现稳定的侧边栏、导航栏与动态内容区的组合布局。

4. 路由守卫的实现方式

React Router v6/v7 中,传统的 onEnter 回调已被更强大的 Loader 机制替代。路由守卫通过在路由配置中定义 loader 函数来实现:在渲染前执行鉴权检查,未登录用户通过 throw redirect('/login') 重定向到登录页,登录后可通过 location.state 回跳原目标页面。

5. React Router v7 的重要更新

React Router v7(2024 年末稳定发布,2026 年为主流版本)融合了 Remix 框架的能力,新增 Loader(数据加载)、Action(表单提交处理)、useNavigation()(导航状态监听)等 API,支持数据预加载和并行加载,大幅提升嵌套路由场景下的加载性能。

七、React 的性能优化手段有哪些?

1. 减少不必要重渲染

  • React.memo:包裹函数组件,通过浅比较(Shallow Comparison)检查 Props 是否变化,未变化时跳过重渲染。需注意:如果 Props 包含对象或函数引用(每次渲染都新建),则 React.memo 无法发挥作用,需配合 useMemo/useCallback 使用
  • useMemo:缓存昂贵的计算结果(如大数据列表排序、过滤),仅在依赖项变化时重新计算
  • useCallback:缓存函数引用,确保传递给子组件的回调函数保持稳定引用,配合 React.memo 才能有效避免子组件重渲染

2. 代码分割与懒加载

通过 React.lazy()<Suspense> 实现组件级代码分割,将不同路由对应的页面拆分为独立的 JS 包,首屏只加载当前页面所需的代码。动态 import() 语法让大型库(如图表库、富文本编辑器)仅在真正需要时加载。

3. 列表虚拟化

当渲染超过 200 条列表数据时,应使用虚拟化技术(如 @tanstack/react-virtual,即原 react-window)只渲染可视区域内的行,将 DOM 节点数量从数千个降低到 10-20 个,大幅提升滚动流畅度。

4. 状态管理优化

避免将频繁变化的状态放在全局 Context 中(每次 Context 值变化都会导致所有消费者重渲染)。应优先使用组件局部状态,全局状态只放置真正需要跨组件共享的数据(如主题、认证信息)。

5. React 19 编译器的自动优化

React Compiler 是独立的构建时优化工具(2025年10月发布稳定版 v1.0),可配合 React 19 使用,能够自动分析组件代码并插入适当的记忆化指令,在多数场景下可替代手动编写 useMemo 和 useCallback 的需要,减少大量重渲染开销。

八、React 的事件机制是怎样的?合成事件是什么?

1. 合成事件(SyntheticEvent)的核心概念

React 并不直接将事件处理函数绑定到 DOM 节点上,而是基于原生事件封装了一套跨浏览器兼容的事件系统,称为合成事件(SyntheticEvent)。当你在 JSX 中写 onClick={handler} 时,传递的并不是原生 DOM 事件,而是 React 封装的统一事件对象。

2. 事件委托机制

React 将所有事件统一委托到应用的根容器(React 17+ 为 #root 节点,React 17 之前为 document)进行监听,而非在每个 DOM 元素上单独绑定监听器。这种机制减少了内存开销,并解决了不同浏览器之间的事件行为差异问题。

3. 事件执行顺序(React 17+)

以点击事件为例,完整的执行顺序为:原生捕获阶段(document → root → div → button)→ React 合成捕获阶段(父组件捕获 → 子组件捕获)→ React 合成冒泡阶段(子组件冒泡 → 父组件冒泡)→ 原生冒泡阶段(button → div → root → document)。

4. 事件池(Event Pooling)的变更

React 16 及更早版本中,合成事件对象会被放入"事件池"中复用,在异步回调(如 setTimeout)中访问事件字段会遇到空值,需调用 e.persist() 保留事件对象。React 17+ 已彻底废弃事件池机制,合成事件对象在事件处理函数执行完毕后即被垃圾回收,可在异步代码中安全访问。

5. 与原生事件的混用注意事项

在 React 中手动绑定原生事件(如 addEventListener)时,需在组件卸载前通过清理函数移除监听,否则会造成内存泄漏。合成事件和原生事件混用时,需清楚两者的执行顺序差异,避免出现预期外的交互行为。

九、React 与 Vue、Angular 等框架相比有什么优缺点?

1. 架构哲学差异

  • React:定位为"UI 库"而非完整框架,只负责视图层,路由、状态管理、构建工具等由社区生态补充。这种"只做一件事并做好"的哲学给予了开发者最大的技术选型自由度,但也导致不同团队的 React 技术栈差异较大
  • Vue:定位为渐进式框架,可以根据需求选择性采用(从在现有页面中嵌入部分交互,到完整单页应用)。单文件组件(SFC)将模板、逻辑和样式放在一个文件中,学习曲线最为平缓
  • Angular:定位为全功能应用框架,内置路由、表单处理、HTTP 客户端、依赖注入等能力,TypeScript 为默认开发语言,适合需要强约束和统一架构的大型团队

2. 学习曲线对比

Vue 的学习曲线最平缓(1-2 周可达到基本生产力),React 次之(2-4 周,主要是理解 JSX 和 Hooks 心智模型),Angular 最陡峭(4-8 周,需掌握 TypeScript、依赖注入、RxJS 等概念)。

3. 性能表现对比

  • 首屏加载速度:Vue(1.2-1.8s)> React(1.4-2.0s,取决于是否使用 Next.js)> Angular(1.8-2.5s)
  • 运行时渲染性能:在正确使用虚拟化的情况下,三者差异不大;Angular 的 Signals 机制(2023+ 引入)显著减少了不必要的重渲染
  • 包体积:Vue 约 16KB(gzip),React 核心约 6KB 但加上 react-dom 后约 40KB,Angular 约 65KB

4. 生态系统与人才市场

React 拥有最大的生态系统(npm 上超过 250 万个包引用 React),招聘市场需求也最高;Angular 的生态较为完整但规模小于 React,主要由企业级应用场景驱动;Vue 的生态在快速增长,但高级开发者的人才供给相对紧张。

5. 选型建议

  • 选择 React:团队需要灵活选型、项目规模会增长到大型企业级、需要最大化的招聘池
  • 选择 Vue:追求最快的上手速度、团队规模中等、项目周期紧张需要快速交付
  • 选择 Angular:企业有严格的代码规范需求、团队有 Java/.NET 背景(熟悉依赖注入模式)、项目周期长且需要强类型约束

十、React 服务器端渲染(SSR)是如何实现的?Next.js 有什么优势?

1. 客户端渲染(CSR)的局限性

传统的 React 单页应用(SPA)在浏览器端完成所有渲染工作:先下载 JS 包,再执行渲染。这导致首屏出现"白屏"、搜索引擎爬虫难以获取页面内容(SEO 不友好)、低网络环境下加载体验差等问题。

2. 服务器端渲染(SSR)的工作原理

SSR 在服务器端完成 React 组件的首次渲染,将生成的完整 HTML 发送给浏览器,浏览器直接展示内容后再"激活"(Hydrate)为可交互的 React 应用。这样用户无需等待 JS 执行即可看到页面内容,同时搜索引擎可以直接抓取到完整 HTML。

3. Next.js 的核心优势

  • 开箱即用的 SSR/SSG 支持:Next.js 是基于 React 的元框架(Meta-framework),默认支持服务端渲染,同时提供静态站点生成(SSG)和增量静态再生成(ISR)能力
  • 文件系统路由:基于 app/pages/ 目录结构自动生成路由,无需手动配置路由表
  • React 服务器组件(RSC):Next.js 深度集成了 React 19 的服务器组件特性,将数据处理和渲染放在服务器端执行,只向浏览器发送最少的 JavaScript,可显著减少客户端 JS 体积
  • 内置性能优化:自动图片优化(WebP/AVIF 格式转换)、代码分割(按路由自动拆分 JS 包)、预加载等关键性能指标优化

4. 渲染模式的选择策略

  • SSG(静态站点生成):适用于博客、文档、营销落地页等内容不频繁变化的场景,构建时预渲染为静态 HTML,托管成本最低、访问速度最快
  • SSR(服务端渲染):适用于需要个性化内容的页面(如用户仪表盘、购物车),每次请求都在服务器端生成最新内容
  • ISR(增量静态再生):结合 SSG 和 SSR 的优点,静态页面可以在后台定期或按需重新生成,无需完整重建整个站点

5. 在腾讯云上的部署建议

React 和 Next.js 应用可部署于腾讯云 CloudBase 平台,其提供开箱即用的 SSR 支持、全球加速 CDN 和自动扩缩容能力,适合面向公网用户的商业级应用部署。

十一、React 组件通信有哪些方式?

1. 父子组件通信(Props 和回调函数)

父组件向子组件传递数据通过 Props(属性)实现,子组件通过父组件传递的回调函数向父组件反馈信息。这是 React 中最基础也是最重要的通信方式,适用于直接父子关系的组件。

2. 兄弟组件通信(状态提升)

兄弟组件之间没有直接通信通道,需将共享状态"提升"到它们最近的共同父组件中,由父组件通过 Props 分别向两个子组件传递状态和回调函数,实现数据同步

3. 跨层级组件通信(Context API)

当组件层级较深(超过 3 层)时,通过 Props 逐层传递数据会产生"Prop Drilling"问题。Context API 允许在组件树中广播数据,任何层级的子组件都可以通过 useContext Hook 直接读取 Context 值,无需中间组件显式传递。

4. 全局状态管理(Redux / Zustand / MobX)

对于在多个不相关组件之间共享的状态(如用户登录信息、主题设置、购物车),使用独立的全局状态管理库是最合适的方案。这类工具提供统一的状态存储、可预测的状态更新和调试工具支持。

5. 组件通信方式的选择原则

  • Props 传递:父子组件 1-2 层深度,数据流向清晰
  • 状态提升:兄弟组件或较浅的组件树
  • Context API:跨多层组件传递但更新频率较低的数据(主题、语言设置)
  • 全局状态库:多组件共享、更新频繁、需要调试追溯的复杂状态

十二、React 中如何实现代码分割和懒加载?

1. React.lazy 和 Suspense 的基础用法

React.lazy() 接受一个动态 import() 函数作为参数,返回一个可延迟加载的 React 组件。Suspense 组件包裹懒加载组件,并指定加载过程中的降级 UI(如加载指示器)。当组件首次渲染时,React 自动发起 JS 包的下载,下载完成后再渲染组件。

2. 基于路由的代码分割

将每个页面拆分为独立的 JS 包是代码分割中收益最高的手段。配合 React Router 使用时,每个路由对应的页面组件都应通过 React.lazy() 加载,这样用户访问不同页面时只下载当前页面所需的代码,可大幅减少初始包体积。

3. 组件级和条件懒加载

对于不是首屏必需的重型组件(如图表编辑器、富文本编辑器、模态框),应根据交互条件动态加载。例如:用户点击"编辑"按钮时才加载编辑器组件,避免所有访问者都提前下载编辑器的代码。

4. 第三方库的按需加载

大型第三方库(如 Chart.js、Monaco Editor、PDF 处理库)应通过动态 import() 按需加载,而非在应用入口处全部导入。配合 React.lazy 或直接在事件处理函数中动态导入,可显著减少初始包体积。

5. 打包分析和优化验证

使用 webpack-bundle-analyzer 或 Vite 的打包可视化工具分析最终生成的 JS 包组成,识别体积过大的模块和重复依赖。结合 Chrome DevTools 的 Coverage 面板(覆盖率分析)找出加载了但未实际执行的代码,针对性地进行懒加载处理。

十三、React 中的高阶组件(HOC)和自定义 Hooks 有什么区别?

1. 高阶组件(HOC)的定义和工作方式

高阶组件是一个函数,接收一个组件作为参数,返回一个新的增强版组件。HOC 的本质是在组件外层包裹一层"容器",通过 Props 注入、生命周期拦截或渲染控制来实现逻辑复用。常见应用场景包括:鉴权检查、日志记录、错误边界包装等。

2. 自定义 Hooks 的定义和工作方式

自定义 Hook 是一个以 use 开头的 JavaScript 函数,内部可以调用其他 Hooks(如 useState、useEffect),将组件逻辑提取为可复用的独立函数。自定义 Hook 不创建额外的组件层级,逻辑直接在调用它的组件内部执行。

3. 核心区别对比

特性

高阶组件(HOC)

自定义 Hooks

实现方式

函数接收组件,返回新组件

函数调用 Hooks,返回状态或方法

组件树影响

增加组件层级(包装地狱)

不增加组件层级

逻辑复用方式

通过包裹增强组件能力

通过调用函数复用状态逻辑

Props 传递

可能出现 Props 命名冲突

调用者自行命名返回值,无冲突

调试体验

组件树中显示多层包裹结构

组件树扁平,调试更清晰

适用组件类型

函数组件和类组件均可

仅限函数组件

4. 当前推荐方案

React 官方和社区在 2025-2026 年的明确推荐是:优先使用自定义 Hooks 进行逻辑复用,HOC 仅用于特定场景(如需要包裹错误边界、需要兼容旧版类组件、第三方库要求使用 HOC 模式)。

5. HOC 仍适用的场景

  • 错误边界(Error Boundary):React 目前仅类组件支持 componentDidCatch,需通过 HOC 包装实现
  • 第三方库集成:某些旧版库(如旧版 React Router、旧版 Redux connect())仍采用 HOC 模式
  • 跨切面关注点:需要在组件渲染外层进行统一的布局包装或 Provider 注入时,HOC 仍有其价值

十四、React 如何进行单元测试和集成测试?

1. 测试金字塔与 React 测试策略

React 应用的测试策略遵循测试金字塔原则:底层是大量的单元测试(快速、隔离、测试单个函数或组件),中间是有限的集成测试(测试多个模块协作),顶层是少量的端到端(E2E)测试(模拟真实用户操作流程)。

2. 单元测试工具链

  • Jest:由 Meta 维护的 JavaScript 测试框架,提供测试运行器、断言库和 Mock 功能,是 React 生态中最主流的测试框架
  • React Testing Library(RTL):官方推荐的 React 组件测试库,核心理念是"以用户使用方式来测试组件",通过角色(Role)、标签文本、占位符等用户可见的特征来查询 DOM 元素,而非测试组件内部实现细节
  • Vitest:基于 Vite 的新一代测试框架,与 Vite 项目零配置集成,执行速度通常快于 Jest

3. 使用 React Testing Library 测试组件

RTL 提供 render() 函数将组件挂载到虚拟 DOM 中,通过 screen.getByRole()screen.getByText() 等方法查询元素,通过 @testing-library/user-event 模拟真实的用户交互(点击、输入、选择等),最后使用 Jest 的 expect() 断言验证行为是否符合预期。

4. 自定义 Hooks 的测试

自定义 Hooks 需要借助 @testing-library/react 提供的 renderHook() API 进行测试:在测试环境中渲染一个调用目标 Hook 的微型组件,然后通过返回值验证 Hook 的状态管理和副作用行为是否正确。

5. 测试最佳实践

  • 优先测试用户可感知的行为,而非组件内部状态结构
  • 使用 getBy* 查询必须存在的元素,使用 queryBy* 断言元素不存在,使用 findBy* 处理异步出现的元素
  • 避免测试实现细节(如不直接调用组件内部的 setState 或私有方法),这样在重构组件内部实现时测试不会失效
  • 配合 jest --coverage 生成测试覆盖率报告,目标覆盖核心业务逻辑和边界条件
相关文章
  • React 进阶 - React Router
    3.2K
  • (React 框架)React技术
    2.3K
  • React源码--React Fiber
    896
  • React 进阶 - React Mobx
    1.8K
  • React 进阶 - React Redux
    2K
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
领券