首页 > 解决方案 > React Native SectionList 性能问题:滚动 React Native SectionList 时 JS 帧率极低

问题描述

对于简单的单元格渲染(单个文本标签),滚动 SectionList 会导致不合理的低 JS 帧率下降(~30),如果单元格内容更复杂(每个单元格中的多个文本标签将导致单个数字 JS 帧),情况会变得更糟利率下降)。

当用户在滚动后点击任何东西时,低 JS 帧速率所体现的用户面临的问题是响应时间非常慢(可能延迟约 5 秒)。

这是一个示例 repo,它在一个屏幕上创建了一个 FlatList 和一个 SectionList,每个都有 10,000 个项目(在屏幕中间横向拆分)。这是一个托管的 Expo 应用程序(为了便于复制),它是用 Typescript 编写的(因为我已经习惯了)。如果您需要,自述文件描述了设置步骤。在物理设备上运行应用,打开 React Native 的性能监视器,查看 JS 帧率。然后尽可能快地滚动每个列表,以查看滚动 FlatList 与 SectionList 时对 JS 帧速率的不同影响。

如果您更喜欢自己引导它,或者在不去 GitHub 的情况下在此处查看它,这里是整个源代码(来自该 repo 的 App.tsx 文件;61 行):

import React from "react"
import { FlatList, SectionList, Text, View } from "react-native"

const listSize = 10_000
const listItems: string[] = Array.from(
  Array(listSize).keys(),
).map((key: number) => key.toString())

const alwaysMemoize = () => true
const ListItem = React.memo(
  ({ title }: { title: string }) => (
    <View style={{ height: 80 }}>
      <Text style={{ width: "100%", textAlign: "center" }}>{title}</Text>
    </View>
  ),
  alwaysMemoize,
)

const flatListColor = "green"
const flatListItems = listItems

const sectionListColor = "blue"
const sectionListItems = listItems.map(listItem => ({
  title: listItem,
  data: [listItem],
}))

const approximateStatusBarHeight = 40

const App = () => {
  const renderItem = React.useCallback(
    ({ item }: { item: string }) => <ListItem title={item} />,
    [],
  )
  const renderSectionHeader = React.useCallback(
    ({ section: { title } }: { section: { title: string } }) => (
      <ListItem title={title + " section header"} />
    ),
    [],
  )

  return (
    <View style={{ flex: 1, paddingTop: approximateStatusBarHeight }}>
      <FlatList
        style={{ flex: 1, backgroundColor: flatListColor }}
        data={flatListItems}
        renderItem={renderItem}
        keyExtractor={item => item}
      />
      <SectionList
        style={{ flex: 1, backgroundColor: sectionListColor }}
        sections={sectionListItems}
        renderItem={renderItem}
        renderSectionHeader={renderSectionHeader}
        keyExtractor={item => item}
      />
    </View>
  )
}

export default App

FlatList JS 帧率性能

SectionList JS 帧率性能

我是否错过了一些性能优化/我做错了什么?或者这是 React Native 的预期表现?

另一个问题作为旁注:如果我没有将每个单元格的高度设置为相当高的高度(例如上面示例中的 80),而只是让高度调整为包含文本的高度(我相信是 14pt) ,两种类型的列表的 JS 帧率下降变得非常糟糕;20 JS 帧或更少。

我还要在这里指出,屏幕截图中显示的性能测试是在 iPhone 13 mini 上完成的。

标签: react-nativeperformancereact-native-sectionlist

解决方案


推荐阅读