React-Native FlatList 刷新问题

580 阅读1分钟

不知道有没有和我一样,有这样一个想法,这个 FlatList 的数据源是 数组,数组也就罢了,更新还要求修改数组地址,不然更新失败。

可能对于我说的这些还不是很清晰,请看下面举例,示例代码如下:

核心部分演示 引入头文件:

import {
  FlatList,
} from 'react-native';

设置数据源:

const [data, setData] = React.useState<{id: string, name: string}[]>([]);

设置渲染组件 FlatList

<FlatList
    ref={ref}
    data={data}
    extraData={data}
    renderItem={renderItem}
/>

注意 如果不设置 extraData 也不会更新。

在更新的时候,下面代码不生效

data.push({id: 'xxx', name: 'ttt' });
data.push({id: 'xxx', name: 'ttt' });
setData(data);

只有这样才生效

data.push({id: 'xxx', name: 'ttt' });
setData([...data]);

这么问题就是,这种生效的模式,相当于重新创建了一个数组,并且通过 setData 进行了事件分发通知。 这是巨大的资源浪费 为什么不能支持 数组元素检查,或者数组元素单个对象的更新。

源码地址


更新:2023年02月18日20:55:01

优化思路:减少数组的申请,减少对象的大量重复创建。

具体实现:双数组 + 数组元素浅拷贝

示例代码:

  const data1 = React.useMemo(() => [] as MessageItemType[], []);
  const data2 = React.useMemo(() => [] as MessageItemType[], []);
  
  const updateDataInternal = React.useCallback(
    (data: MessageItemType[]) => {
      if (data === data1) {
        console.log('test:data1');
        for (let index = 0; index < data1.length; index++) {
          const element = data1[index] as MessageItemType;
          data2[index] = element;
        }
        data2.splice(data1.length, data2.length);
        setItems(data2);
      } else if (data === data2) {
        console.log('test:data2');
        for (let index = 0; index < data2.length; index++) {
          const element = data2[index] as MessageItemType;
          data1[index] = element;
        }
        data1.splice(data2.length, data1.length);
        setItems(data1);
      } else {
        throw new Error('This is impossible.');
      }
    },
    [data1, data2]
  );

源码地址