RN开发搬砖经验之-如何处理FlashList组件加载后调用scrollToIndex没有滚动指定位置

前言

如题,这里只能说是处理,起正向作用的临时方案,因为我也着实没搞懂这个BUG的具体原因,看github上有提相关的issuesFor long lists with different item types scrollToIndex does not work reliable,但看官方没有给出具体的解决方案!

我遇到的case跟上面issues差不多,都是long lists------即数据量比较大的列表,大概有500左右的数据项,然后上面是列表项是不同类型的(估计是聊天消息对框话之类的列表吧),但我这边列表项是同一种类型的,每个列表项需要显示一张小的缩略图以及相关的文字描述。

所以这个问题可以归类为长列表下当FlashList被加载后,马上调或延迟较少时间调scrollToIndex接口滚动到比较后面位置时,该接口可能不会按预期工作---没有滚动指定位置/指定列表项

问题场景

出现问题场景的前提

1、列表数据项500个左右

2、当列表被加载后,延迟几十ms再调scrollToIndex滚动到400项

结果:有概率没有滚动第400项,性能越差手机越容易重现,特别性能差的手机是必现的

抽像的示例代码如下:

import React, { useRef, useEffect } from 'react';  
import { View, Text, StyleSheet } from 'react-native';  
import FlashList from '@shopify/flash-list';  
  
const data = [  
  { id: 1, title: 'Item 1' },  
  { id: 2, title: 'Item 2' },  
  { id: 3, title: 'Item 3' },  
  // ...更多数据项  ,有500项
];  
  
const ItemComponent = ({ item }) => (  
  <View style={styles.item}>  
    <Text>{item.title}</Text>  
  </View>  
);  
  
const MyFlashList = () => {  
  const flashListRef = useRef(null);  
  
  useEffect(() => {  
    if (flashListRef.current) {  
      // 延迟执行滚动操作,确保列表已经渲染完成  
      setTimeout(() => {  
        flashListRef.current.scrollToIndex({ index: 400, animated: true });  
      }, 20);  
    }  
  }, []); // 空数组表示这个 effect 只在组件挂载和卸载时运行  
  
  return (  
    <FlashList  
      ref={flashListRef} // 将 ref 传递给 FlashList  
      data={data}  
      renderItem={({ item }) => <ItemComponent item={item} />}  
      keyExtractor={item => String(item.id)}  
      ItemSeparatorComponent={() => <View style={styles.separator} />}  
      estimatedItemSize={50}  
      maxToRenderPerBatch={10}  
      windowSize={21}  
    />  
  );  
};  
  
const styles = StyleSheet.create({  
  item: {  
    backgroundColor: '#f9c2ff',  
    padding: 20,  
    marginVertical: 8,  
    height: 50
  },  
  separator: {  
    height: 1,  
    backgroundColor: 'rgba(0, 0, 0, 0.1)',  
  },  
});  
  
export default MyFlashList;

临时方案

延时操作是必须的,如果延时2S,大多数手机都会正常的滚动到指定的位置,就算是UI加上loading,也是比较影响用户体验的!同时你也不能保持2S能兼容到你需要兼之的Android设备。延时能起到正向的作用,估计是跟FlashList的内部实现有关,当我们有做延时操作,意味着FlashList有时间在其它内部完全加载与真正完处理好数据与渲染,自然到我们调用滚动接口时就能滚动到我们期望的位置了。

我的临时方案是参考github上的小哥,但我比较保险一点,能提高Flash性能的相关配置我都用了,比如estimatedItemSize也配置,滚动时不需要动画等

即FlashList的配置如下,保险起见,getItemLayout也配置上,getItemLayout是FlatList的属性

// 50是列表项的高度值,这里是固定长度,且只有种列表项类型
    <FlashList  
      ref={flashListRef} // 将 ref 传递给 FlashList  
      data={data}  
      renderItem={({ item }) => <ItemComponent item={item} />}  
      keyExtractor={item => String(item.id)}  
      estimatedItemSize={83}
            getItemLayout={(data, index) => ({
              length: 50,
              offset: 50 * index,
              index,
            })}
            overrideItemLayout={(layout, item, index, maxColumns) => {
              layout.size = 50;
            }}
      windowSize={21}  
    />  

总结:以上临时方案是不在调整延时值的情况下,尽可能让scrollToIndex滚动到预期的位置,没有根本上解决与搞清楚相关的逻辑!

相关说明

FlatList也有类似的问题

[Auto scrollToIndex FlatList doesn't work in long lists](Auto scrollToIndex FlatList doesn't work in long lists)

FlashList的性能相关配置

https://shopify.github.io/flash-list/docs/fundamentals/performant-components

考虑方案

1、第一:从产品层出考虑,长列表数据加载后,定时给一两秒的个Loading的状态,再做滚动操作;

2、第二:从技术页面,分段分页加载长列表数据,这个就比较复杂,还要考虑处理滚动的目标处于那个分页等等逻辑

相关推荐
前端小小王24 分钟前
React Hooks
前端·javascript·react.js
迷途小码农零零发34 分钟前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
真滴book理喻4 小时前
Vue(四)
前端·javascript·vue.js
程序员_三木4 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
不是鱼5 小时前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
开心工作室_kaic6 小时前
springboot476基于vue篮球联盟管理系统(论文+源码)_kaic
前端·javascript·vue.js
川石教育6 小时前
Vue前端开发-缓存优化
前端·javascript·vue.js·缓存·前端框架·vue·数据缓存
搏博6 小时前
使用Vue创建前后端分离项目的过程(前端部分)
前端·javascript·vue.js
温轻舟6 小时前
前端开发 之 12个鼠标交互特效上【附完整源码】
开发语言·前端·javascript·css·html·交互·温轻舟
web135085886356 小时前
2024-05-18 前端模块化开发——ESModule模块化
开发语言·前端·javascript