组件思考-FlatList

93 阅读2分钟

忘记extraData(2022-09-20)

const App = () => {
  const [selectedId, setSelectedId] = useState(null);

  const renderItem = ({ item }) => {
    const backgroundColor = item.id === selectedId ? "#6e3b6e" : "#f9c2ff";

    return (
      <Item
        item={item}
        onPress={() => setSelectedId(item.id)}
        style={{ backgroundColor }}
      />
    );
  };

  const renderHeader = () => {
    return (
      <h1>Header</h1>
    );
  };

  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        data={DATA}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        ListHeaderComponent={renderHeader}
      />
    </SafeAreaView>
  );
};

上面那段代码,似乎一切都正常了,甚至运行时,也没有报错。但是我们注意到,renderItem中,引用了除了data之外的数据selectedId。任何除了data外的数据,在被renderItem或者其他诸如ListHeaderComponent之类的属性使用的时候,都要把这些数据放到extraData里。

<FlatList
    ....
    extraData={selectedId}
/>

onViewableItemsChanged(2022-09-19)

这是一个很有用,但是却不被经常用到的的属性。它的意思是说,当我手动滑动我的List里的Items时,当这些items每次出现在屏幕中的items有变化时,都触发这个属性连的回调函数。片段代码如下:

  const itemsChanged = ({viewableItems}) => {
    console.dir(viewableItems)
  };

  return (
    <SafeAreaView style={styles.container}>
      <FlatList
        ... ...
        onViewableItemsChanged={itemsChanged}
      />
    </SafeAreaView>
  );

第一个动画是我的手指在上下滑动items,可以看到某个时刻,出现在屏幕上的items或者是6个,或者是7个。

onViewableItemsChanged.mobile.gif

第二个动画是控制台打出的log,随着我手指滑动,只要onViewableItemsChanged被触发,就会打出一个log。

onViewableItemsChanged.log.gif

viewabilityConfig

这又是一个不常用的属性,它本质上是定义了什么情况下,才叫‘Viewable’。并不是说,当我滑动手指时,眼睛看到一个item从无到有才叫Viewable,这里的定义不是指的人类眼睛看到的,而是只系统认定的Viewable,当系统认定,当前情况属于Viewable的时候,它会触发onViewableItemsChanged。下面这个图,就是当我给FlatList加了如下属性后,控制台的输出。

  const viewabilityConfig = {
    itemVisiblePercentThreshold: 95
  }
  
  <FlatList
    ... ...
    viewabilityConfig={viewabilityConfig}
  />
image.png

显然,这种情况下,因为只有一个item暴露出95%以上,系统才会调用它会触发onViewableItemsChanged。这也就解释了,为什么我肉眼看在手机屏幕上看到的Items没有任何变化,但是控制台的输出中,items的数量却少了的原因。