尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
React Native FlashList 测试指南:用 Jest 模拟布局测量,为高性能列表编写单元测试
移动开发UI组件跨平台【免费下载链接】flash-listA better list for React Native项目地址https://gitcode.com/gh_mirrors/fl/flash-list点击查看免费下载FlashList 是 React Native 平台上 FlatList 的高性能替代方案其核心渲染机制建立在延迟挂载 布局测量之上组件不会立即渲染列表项而是先测量底层ScrollView的尺寸再按窗口大小决定挂载哪些 item。这一机制在 Jest 的 jsdom 测试环境中无法自然触发因此 FlashList 官方提供了专门的 Jest 预设通过 mock 布局测量函数让列表在测试中立即有尺寸可用。本文基于 FlashList 1.x 官方测试文档结合仓库源码完整讲解 Jest 测试环境的搭建步骤、jestSetup.js的底层原理、基于testing-library/react-native的测试写法以及 FlashList 仓库自身的测试实践帮助你为自己的列表组件编写可靠、可复现的单元测试。为什么 FlashList 在测试环境中需要特殊处理普通 React Native 组件在 Jest 中可以直接渲染但 FlashList 走的是另一条路径。在官方 1.x 测试文档中作者明确给出了原因SinceFlashListdoes not immediately render but waits for the size of the underlyingScrollView(unless you specifyestimatedListSize), we need to mock triggeringonLayoutevent.翻译过来就是FlashList 并不会立刻渲染列表项而是等待底层ScrollView的尺寸确定后才开始挂载 item——除非你显式传入了estimatedListSize属性。因此在测试环境中我们需要 mock 掉触发onLayout事件这一环节。从1.x 使用文档可以查到estimatedListSize的定义estimatedListSize?: { height: number; width: number }它是列表可见区域的估算宽高注意不是滚动内容的总尺寸。显式指定该属性后列表可以在首帧立即渲染无需先测量自身尺寸不指定时列表必须先完成一次测量导致首次渲染存在微小延迟。在测试环境jsdom中真实的measureLayout调用无法返回有效值所以等待测量会让列表永远挂载不出任何 item——这正是需要 mock 的根因。版本提示estimatedListSize是 FlashList 1.x 的属性。从仓库的 v2-changes.md 看v2 中该属性已不再使用如果按本文配置 mock 方案则无需依赖该属性。官方 Jest 预设jestSetup.js的工作原理FlashList 在包根目录提供了现成的 Jest 预设文件 jestSetup.js并在 package.json 的files字段中明确包含它jestSetup.js确保发布到 npm 后用户可以直接引用。完整内容如下jest.mock(shopify/flash-list/dist/recyclerview/utils/measureLayout, () { const originalModule jest.requireActual( shopify/flash-list/dist/recyclerview/utils/measureLayout ); return { ...originalModule, measureParentSize: jest.fn().mockImplementation(() ({ x: 0, y: 0, width: 400, height: 900, })), measureFirstChildLayout: jest.fn().mockImplementation(() ({ x: 0, y: 0, width: 400, height: 900, })), measureItemLayout: jest.fn().mockImplementation(() ({ x: 0, y: 0, width: 100, height: 100, })), }; });这段代码的核心动作是用jest.mock替换measureLayout模块中的三个关键函数让它们无论何时被调用都返回固定的测量结果。其设计意图与源码注释完全对应——在 src/recyclerview/utils/measureLayout.ts 中这三个函数都被明确标注为方便 mockmeasureParentSize(view)测量 RecyclerView 外层容器的尺寸。源码注释写着 Specific method for easier mocking内部通过measureLayoutRelative(view, view, undefined)同步拿到{ width, height }。mock 后固定返回400 × 900相当于模拟了一个 400 宽、900 高的列表窗口。measureFirstChildLayout(childContainerView, parentView)测量子容器相对父容器的布局用于推算第一个 item 的偏移量x/y坐标。mock 后固定返回{ x: 0, y: 0, width: 400, height: 900 }即子容器与父容器完全重合首项偏移为 0。measureItemLayout(item, oldLayout)测量单个列表项的布局是回收复用机制判断该项尺寸是否变化的依据。mock 后每个 item 固定为100 × 100让布局管理器可以确定每屏能放多少个 item。正是因为这三个函数返回了确定值FlashList 的等待onLayout环节被彻底绕开RecyclerView挂载后立刻拿到窗口尺寸与 item 尺寸随即开始挂载首屏 item。这就是require(shopify/flash-list/jestSetup)一行代码解决测试环境渲染问题的完整原理。配置 Jest 测试环境第一步创建 jest-setup.js 并引入官方预设在你的项目根目录新建或打开已有的jest-setup.js文件加入一行require(shopify/flash-list/jestSetup);这行代码会在每个测试文件执行前运行完成对measureLayout模块的全局 mock。第二步检查 jest.config.js 配置接着确认你的 jest.config.js或 package.json 中的jest字段包含以下两个关键项... preset: react-native, setupFiles: [./jest-setup.js], ...preset: react-native使用 React Native 官方 Jest 预设负责处理 RN 组件、react-native模块等原生模块的转换与 mock仓库自身的 jest.config.js 同样使用该 preset。setupFiles: [./jest-setup.js]在测试框架安装之前执行 setup 文件确保 mock 先于测试代码生效。注意这里是setupFiles而不是setupFilesAfterEach顺序不同会导致 mock 时机错误。配置完成后运行jest仓库中对应的脚本是 package.json 里的test: jest列表即可在测试环境中正常渲染。编写第一个组件测试完成环境配置后就可以用testing-library/react-native编写测试了。以下是官方文档给出的完整示例import React from react; import { render } from testing-library/react-native; describe(MyFlashListComponent, () { it(renders items, () { const { getByText } render(MyFlashListComponent /); const element getByText(Title of one of the items); // Do something with element ... }); });要点说明render(MyFlashListComponent /)会挂载你的列表组件。得益于jestSetup.js的 mock列表不再卡在等待测量阶段而是立即按400 × 900的窗口尺寸、100 × 100的 item 尺寸挂载首屏 item。getByText(Title of one of the items)用于断言列表渲染出了指定内容的 item你可以继续用返回的element做交互模拟、样式断言等后续验证。如果首屏按 mock 尺寸计算900 / 100 ≈ 9 行没有渲染出你查找的 item请检查它是否真的排在列表头部或者需要配合scrollTo/onViewableItemsChanged等能力滚动后再断言。深入原理真实环境中的布局测量链路理解了 mock 方案后再回到真实运行环境中看这三个函数被谁调用、如何影响渲染能让你在排查为什么测试和真机行为不一致时更有把握。在 src/recyclerview/RecyclerView.tsx 中组件挂载时通过useLayoutEffect执行初始化测量useLayoutEffect(() { if (internalViewRef.current firstChildViewRef.current) { const outerViewSize measureParentSize(internalViewRef.current); const firstChildViewLayout measureFirstChildLayout( firstChildViewRef.current, internalViewRef.current ); containerViewSizeRef.current outerViewSize; // firstChildViewLayout 已是相对外层容器的坐标其 x/y 直接给出首项偏移 const firstItemOffset horizontal ? firstChildViewLayout.x : firstChildViewLayout.y; recyclerViewManager.updateLayoutParams( { width: horizontal ? outerViewSize.width : firstChildViewLayout.width, height: horizontal ? firstChildViewLayout.height : outerViewSize.height, }, // RTL 横向列表需要额外换算偏移 isHorizontalRTL recyclerViewManager.hasLayout() ? firstItemOffset - recyclerViewManager.getChildContainerDimensions().width : firstItemOffset ); } });可以看到measureParentSize与measureFirstChildLayout的结果直接决定了updateLayoutParams拿到的窗口尺寸和首项偏移——这是布局管理器计算该挂载哪些 item的起点。而measureItemLayout则用于后续每个 item 的尺寸更新与回收复用判定。因此 mock 这三个函数本质上就是把测量这一步从真实 DOM 操作替换为固定值从而让整条渲染链路在 Jest 中顺畅运转。真实环境中measureLayout.ts 的实现依赖 React Native 的view.measureLayout()原生方法并借助PixelRatio.roundToNearestPixel消除浮点精度误差areDimensionsEqual允许 1px 容差。Jest 环境无法执行这些原生调用这正是官方提供预设而不是让用户手动 mock 的原因。FlashList 仓库自身的测试实践FlashList 仓库本身就是这套 mock 方案的最大用户可以作为你编写测试时的参考范本。在 src/tests/RecyclerView.test.tsx 中仓库同样在文件顶部 mock 了measureLayout窗口尺寸 mock 为399 × 899、item 为100 × 100然后断言首屏渲染行为jest.mock(../recyclerview/utils/measureLayout, () { const originalModule jest.requireActual( ../recyclerview/utils/measureLayout ); return { ...originalModule, measureParentSize: jest.fn().mockImplementation(() ({ width: 399, height: 899, })), measureFirstChildLayout: jest.fn().mockImplementation(() ({ x: 0, y: 0, width: 399, height: 899, })), measureItemLayout: jest.fn().mockImplementation(() ({ x: 0, y: 0, width: 100, height: 100, })), }; }); it(renders items, () { const result renderRecyclerView({}); expect(result).toContainReactComponent(Text, { children: 0 }); expect(result).not.toContainReactComponent(Text, { children: 11 }); });这个测试非常直观地验证了回收渲染的核心语义按 mock 尺寸计算首屏只会挂载约 9 个 item因此children: 0的 item 存在而超出首屏的children: 11不应被渲染。同样的 mock 模式还出现在 LayoutCommitObserver.test.tsx、StickyHeaders.test.tsx 等测试文件中你可以按需查阅。仓库的 jest.config.js 还配置了transformIgnorePatterns放行react-native相关包与自定义resolvershared/testing/resolver.js如果你在接入 FlashList 后遇到模块解析问题可以参考这些配置调整自己的 Jest 设置。常见问题与注意事项mock 尺寸如何影响测试断言官方预设将窗口固定为400 × 900、item 固定为100 × 100即一屏约 9 个 item。若你的业务测试依赖更多 item 可见可以在自己的jest-setup.js中复制官方 jestSetup.js 的写法自行调整返回的宽高数值参照仓库测试中399 × 899的做法。为什么要用setupFiles只有setupFiles会在测试框架安装前执行jest.mock如果误配到setupFilesAfterAllmock 将不会生效列表依旧无法渲染。v1 与 v2 的差异本文配置基于 FlashList 1.x 官方测试文档当前仓库版本为 2.3.3estimatedListSize在 v2 已废弃见 v2-changes.md 与 v2-migration.md但 mockmeasureLayout的核心思路在 v2 的当前测试文档中同样适用。总结FlashList 的 Jest 测试方案可以归纳为一条主线列表渲染依赖布局测量测试环境无法执行真实测量因此用固定返回值 mock 测量函数。具体落地只需三步创建jest-setup.js并require(shopify/flash-list/jestSetup)、在jest.config.js中配置preset: react-native与setupFiles、然后用testing-library/react-native的rendergetByText断言首屏 item 的渲染结果。理解了measureParentSize/measureFirstChildLayout/measureItemLayout三个函数在渲染链路中的作用见 RecyclerView.tsx 的初始化测量逻辑你就能举一反三既可以按需定制 mock 尺寸也能在遇到测试能渲染但行为异常时快速定位到是测量值不符合预期还是渲染窗口设置不当。赞分享移动开发UI组件跨平台【免费下载链接】flash-listA better list for React Native项目地址https://gitcode.com/gh_mirrors/fl/flash-list点击查看免费下载相关推荐Tendis集群管理完全手册从零搭建千节点分布式系统Tendis集群管理完全手册从零搭建千节点分布式系统 Tendis作为一款高性能分布式存储系统完全兼容Redis协议为大规模数据存储提供了可靠解决方案。本数据库KV存储分布式数据库深入源码解析lambda_resnet26rpt_256.c1_in1ktimm库中的实现细节深入源码解析lambda_resnet26rpt_256.c1_in1ktimm库中的实现细节 lambda_resnet26rpt_256.c1_in1k是tui.editor单元测试模拟使用Jest测试编辑器功能tui.editor单元测试模拟使用Jest测试编辑器功能 在前端开发中单元测试是确保代码质量的关键环节。对于富文本编辑器这类复杂组件测试环境的配置尤为重前端UI组件上一篇Lo-Fi Player开发解析Tone.js与Web Audio API如何实现高品质音频合成下一篇OpenClaw Tavily 插件实战为 Agent 接入结构化网页搜索与 URL 内容提取创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Learn X in Y minutes 法文版 HTML 指南精讲:从零掌握 HTML5 标记语言核心语法

Learn X in Y minutes 法文版 HTML 指南精讲:从零掌握 HTML5 标记语言核心语法

文档教程 【免费下载链接】learnxinyminutes-docs Code documentation written as code! How novel and totally my idea! 项目地址: https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs 点击查看 免费下载 本篇指南以 learnxinyminutes-docs 仓库中的 fr/h…

📅 2026/10/8 1:29:11
Hudi 复合记录键与大写字段名 COW 表构建与验证指南:Trino 连接器记录级索引剪枝实战

Hudi 复合记录键与大写字段名 COW 表构建与验证指南:Trino 连接器记录级索引剪枝实战

数据湖湖仓一体大数据数据存储 【免费下载链接】hudi Upserts, Deletes And Incremental Processing on Big Data. 项目地址: https://gitcode.com/gh_mirrors/hud/hudi 点击查看 免费下载 导读 本文以 hudi-trino 测试数据集中的生成脚本为核心,讲解如…

📅 2026/10/8 1:29:11
ProxySQL Cluster 内部机制深度解析:节点监控线程、校验和同步与配置收敛原理

ProxySQL Cluster 内部机制深度解析:节点监控线程、校验和同步与配置收敛原理

后端数据库负载均衡 【免费下载链接】proxysql High-performance proxy for MySQL and PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/pr/proxysql 点击查看 免费下载 导读 本文深入解析 ProxySQL 高可用集群(ProxySQL Cluster)的内…

📅 2026/10/8 1:29:11
MORE NEWS

更多资讯

📰

iOS工程实战清单:开发者模式、链接唤起与后台音频排坑指南

iOS 第九章终于更新了。注意,这里的“iOS 第九章”不是 iOS 9 系统,也不是某个新框架的版本号,而是很多人一直在跟的 iOS 开发进阶系列里的最新一章。这章之所以比前面几章更难产,并不是因为它要讲什么新潮模型或者复杂的底层原理…

📰

iOS开发全流程:从环境搭建、真机调试到上架准备

兄弟们,iOS 系列的第九章终于更新了。这一章等得确实有点久,后台也一直有读者在催更。如果说前八章我们更多是在单个知识点上打转,那第九章的核心目标就很明确了:把之前零散的能力串成一条完整的 iOS 应用开发主线——从环境准备、…

📰

Windows 上通过 Cygwin 编译运行 Varnish 缓存实战指南

简介:Cygwin Varnish Cache 是一套面向 Windows 平台开发者与运维人员的开源修补方案,旨在解决 Varnish Cache 这款高性能 HTTP 缓存服务器无法直接在 Cygwin 模拟环境中运行的问题。项目通过对源码进行适配改造,覆盖文件路径处理、网络 I/O、…

📰

MinIO分片上传与断点续传:Java大文件上传实战避坑指南

简介:这是一份面向 Java 后端开发者的 MinIO 分片上传与断点续传实战示例,针对大文件直传易超时、网络中断需重传等痛点,给出可直接运行的完整方案。压缩包共 13 个文件,约 19KB,包含 7 个 Java 源码、2 个 JavaScript…

📰

eSIM-Tools通知系统开发指南:用Netlify Functions构建轻量级Toast通知的最佳实践

eSIM-Tools通知系统开发指南:用Netlify Functions构建轻量级Toast通知的最佳实践 【免费下载链接】eSIM-Tools 专为已有 Giffgaff 和 Simyo 号码的用户设计的现代化 eSIM 管理工具集,支持将物理 SIM 卡转换为 eSIM、设备更换和二维码生成。(A modern set…

📰

群晖NAS部署Dify:从零构建可维护的本地大模型平台

简介:本资源是专为群晖NAS用户设计的Dify开源AI应用部署安装包,面向希望在本地私有化环境中快速搭建大模型应用服务的开发者与技术爱好者,解决Synology平台缺乏官方Dify支持、手动部署门槛高的实际问题。压缩包共2000个文件,主体为…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬