RN长列表(FlatList)性能优化的具体手段有哪些?

一、先理解 FlatList 为什么会卡

FlatList 本质是一个"虚拟列表(VirtualizedList)",它的性能瓶颈主要来自:

  1. JS 线程计算压力

  2. 频繁 re-render

  3. 布局计算(measure)

  4. Bridge 通信(JS ↔ Native)

  5. 内存占用过大


二、核心优化手段(必会)

1️⃣ 控制渲染窗口(最关键)

复制代码
<FlatList
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
/>

参数解释:

  • initialNumToRender:首屏渲染多少条

  • maxToRenderPerBatch:每批渲染数量

  • windowSize:渲染区域(单位:屏)

👉 推荐经验值:

复制代码
initialNumToRender: 8~12
maxToRenderPerBatch: 8~16
windowSize: 5~10

📌 原理:减少一次性渲染数量,降低 JS 压力


2️⃣ 使用 getItemLayout(强烈推荐)

复制代码
getItemLayout={(data, index) => ({
  length: ITEM_HEIGHT,
  offset: ITEM_HEIGHT * index,
  index,
})}

👉 适用于:item 高度固定

📌 作用:

  • 跳过 measure(布局测量)

  • scrollToIndex 更精准

  • 减少卡顿

👉 这是性能优化里收益最大之一


3️⃣ 避免不必要的 re-render(核心)

✅ 使用 React.memo

复制代码
const Item = React.memo(({ item }) => {
  return <Text>{item.title}</Text>;
});

✅ keyExtractor 稳定

复制代码
keyExtractor={(item) => item.id}

❌ 避免:

复制代码
keyExtractor={(item, index) => index.toString()}

✅ renderItem 不要每次新建函数

复制代码
const renderItem = useCallback(({ item }) => {
  return <Item item={item} />;
}, []);

4️⃣ 使用 shouldComponentUpdate / memo

复杂 item 必做:

复制代码
export default React.memo(Item, (prev, next) => {
  return prev.item === next.item;
});

📌 避免整列表更新


5️⃣ 使用 removeClippedSubviews

复制代码
<FlatList removeClippedSubviews />

📌 作用:

  • 移除屏幕外组件

  • 减少内存占用

⚠️ 注意:

  • 有时候会导致闪烁(尤其动画)

6️⃣ 减少 renderItem 复杂度

❌ 不要在 render 里做:

  • 复杂计算

  • JSON 处理

  • 大量逻辑判断

✅ 提前处理数据:

复制代码
const processedData = useMemo(() => {
  return data.map(...)
}, [data]);

7️⃣ 避免 inline style

复制代码
<View style={{ padding: 10 }} />

复制代码
const styles = StyleSheet.create({
  item: { padding: 10 },
});

📌 减少重复创建对象


8️⃣ 分页 / 懒加载(必须)

复制代码
onEndReached={loadMore}
onEndReachedThreshold={0.5}

📌 不要一次性加载几千条数据


9️⃣ 使用 ListHeaderComponent / ListFooterComponent

避免在外层包一层 ScrollView:

复制代码
<ScrollView>
  <FlatList />
</ScrollView>

👉 直接用:

复制代码
<FlatList
  ListHeaderComponent={<Header />}
  ListFooterComponent={<Footer />}
/>

🔟 控制更新频率(大数据场景)

复制代码
extraData={selectedId}

📌 只在必要时触发更新


三、进阶优化(大厂级)

🚀 1. 使用 FlashList(性能碾压)

👉 Shopify 出的:

复制代码
npm install @shopify/flash-list

import { FlashList } from "@shopify/flash-list";

📌 优势:

  • 更少掉帧

  • 更好的内存管理

  • 自动优化布局

👉 在大数据场景建议直接替换 FlatList


🚀 2. RecyclerListView(极致优化)

👉 更底层:

  • 完全自定义布局

  • 适合超大数据(万级)

但:

👉 使用复杂度高


🚀 3. 使用 InteractionManager

延迟非关键渲染:

复制代码
InteractionManager.runAfterInteractions(() => {
  // 非关键任务
});

🚀 4. 避免频繁 setState

复制代码
// ❌
setList([...list, newItem]);

// ✅ 批量更新

四、性能优化 checklist(实战必看)

你可以对照排查:

  • 是否使用 getItemLayout?

  • item 是否 memo?

  • renderItem 是否 useCallback?

  • key 是否稳定?

  • 是否分页加载?

  • 是否避免 inline object?

  • windowSize 是否合理?

  • 是否避免大对象传递?

  • 是否减少 bridge 通信?


五、给你一个推荐配置(通用模板)

复制代码
<FlatList
  data={data}
  renderItem={renderItem}
  keyExtractor={(item) => item.id}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={7}
  removeClippedSubviews
  getItemLayout={getItemLayout}
  onEndReached={loadMore}
/>

六、总结一句话

👉 FlatList 优化本质就是:

减少渲染数量 + 减少重渲染 + 减少计算 + 减少通信

相关推荐
To_OC12 小时前
别只拿 useRef 绑 DOM 了,搭配 Web Worker 解决页面卡顿才是真的香
前端·react.js·dom
小当家.10514 小时前
深入理解 ReAct Agent:从原理到 Java 实战
java·react.js·agent·react·架构设计·agent设计
阿黎梨梨18 小时前
React 表单处理与性能优化:从入门到进阶
前端·react.js
breeze jiang19 小时前
React memo、useCallback 与 useMemo:父组件多状态时如何减少无效渲染
前端·javascript·react.js
今天的砖头有点烫手啊20 小时前
AI Agent 开发实战(十):Agent 设计模式(ReAct / Plan-Execute / Reflection)
人工智能·react.js·设计模式
橘色的喵21 小时前
ARM-Linux 嵌入式消息总线:高优先级驱逐机制设计
linux·arm开发·性能优化·嵌入式·newosp
不好听6131 天前
React useContext:跨层级共享数据的上下文
react.js
不好听6131 天前
React 自定义 Hook:把响应式与副作用装进 useXxx
react.js
触底反弹1 天前
🏗️ 写完 Todos 之后,大型 React 项目的 7 个架构真相
前端·react.js·前端框架