You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactNative中SectionList重渲染卡顿优化及加载提示实现方法

优化方案

一、性能优化方案

  • 修复内联函数导致的重渲染问题
    现有代码里的renderItem、renderSectionHeader都是内联定义的,每次组件渲染都会生成新的函数引用,即使OrderItem用了React.memo,也会因为props中的函数引用变化触发重渲染。
    优化方法:
  1. 把三个渲染相关函数提取到组件外部,或者用useCallback包裹,保证函数引用稳定
  2. 不要在renderItem里透传navigation,改用OrderItem内部调用useNavigation()获取导航实例,减少props传递的变量
    示例修改:
// 组件外部定义或者用useCallback包裹
const keyExtractor = (item) => item.id;
const renderSectionHeader = ({ section: { name } }) => (
  <Text fontSize="sm" color="grey" py="2" px="4" bg="lightgrey">
    {name}
  </Text>
);
const renderItem = ({ item }) => <OrderItem order={item} />;

// SectionList调用
<SectionList
  sections={internalOrders}
  keyExtractor={keyExtractor}
  renderItem={renderItem}
  renderSectionHeader={renderSectionHeader}
  removeClippedSubviews={true}
  maxToRenderPerBatch={5}
  windowSize={5}
/>
  • 优化Redux Selector缓存
    当前的筛选分组逻辑如果没有做缓存,每次redux状态变动都会重新计算分组,返回全新的sections数组引用,即使内容没有变化也会触发SectionList全量重渲染。
    用reselect库创建带缓存的selector,只有当依赖的原始订单数据、筛选条件发生变化时,才重新计算分组结果,否则返回之前的缓存引用,避免不必要的重渲染。
  • 完善React.memo的比较逻辑
    React.memo默认只做浅比较,如果order属性每次都是新的对象引用,即使内容完全一致也会触发重渲染。给React.memo传入第二个自定义比较函数,只比较OrderItem实际用到的字段:
// OrderItem组件定义处
export default React.memo(OrderItem, (prevProps, nextProps) => {
  // 只比较实际渲染用到的字段,比如id、订单状态、金额等
  return prevProps.order.id === nextProps.order.id
    && prevProps.order.status === nextProps.order.status
    && prevProps.order.amount === nextProps.order.amount;
});
  • SectionList自带属性优化
    开启removeClippedSubviews={true}自动裁剪屏幕外的视图,调整maxToRenderPerBatch、initialNumToRender为刚好覆盖一屏的数量,windowSize设置为5左右(不要用默认的21,减少同时渲染的视图数量)。

二、加载Spinner实现方案

可以通过拆分渲染时序实现,避免用户感知卡顿:

  1. 在redux中新增一个listLoading状态,触发筛选/分组操作前,先将listLoading设为true,此时页面优先渲染Spinner组件
  2. 用InteractionManager.runAfterInteractions()包裹筛选分组的触发逻辑,等Spinner渲染完成后再执行耗时的计算和列表渲染逻辑,计算完成后再将listLoading设为false
    示例代码:
// 触发筛选的逻辑
const handleFilter = useCallback((filterParams) => {
  dispatch(setListLoading(true));
  InteractionManager.runAfterInteractions(() => {
    // 执行筛选分组的action,计算完成后自动更新sections数据
    dispatch(filterOrders(filterParams));
    dispatch(setListLoading(false));
  });
}, [dispatch]);

// 组件渲染处
return (
  <View style={{flex: 1}}>
    {listLoading ? (
      <ActivityIndicator style={{flex: 1}} size="large" />
    ) : (
      <SectionList {/* 原有配置 */} />
    )}
  </View>
)

如果卡顿问题还是存在,可以将筛选分组的逻辑放到独立的工作线程执行,避免阻塞JS主线程的UI渲染。

内容的提问来源于stack exchange,提问作者holyris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 10:21:02