javascript React Native平面列表警告:虚拟化列表:您的列表很大,更新速度很慢&挂起的回调数量过多

i86rm4rw  于 2023-02-28  发布在  Java
关注(0)|答案(1)|浏览(234)

我有一个表情对象的本地数组(4000+),我在模态渲染。
通过研究,我发现使用Flatlist对性能最好。它在应用程序中工作,虽然有点滞后,但我在终端中得到两个警告:

Please report: Excessive number of pending callbacks: 501. 
Some pending callbacks that might have leaked by never being called from 
native code

&

VirtualizedList: You have a large list that is slow to update 
- make sure your renderItem function renders components that 
follow React performance best practices like PureComponent, shouldComponentUpdate, etc. 
{"contentLength": 4239.66650390625, "dt": 607, "prevDt": 514}

下面是我的代码:

export const EmojiPicker = () => {
  const [showModal, setShowModal] = useState(false);
  const [selectedEmoji, setSelectedEmoji] = useState(() => {
    const random = Math.floor(Math.random() * emojis.length);
    return emojis[random];
  });

  const renderEmoji = (emoji) => {
    return (
      <TouchableOpacity
        onPress={() => {
          setSelectedEmoji(emoji);
          setShowModal(!showModal);
        }}
      >
        <Text style={styles.emoji} size={30}>
          {emoji.char}
        </Text>
      </TouchableOpacity>
    );
  };

  return (
    <>
      <TouchableOpacity
        onPress={() => setShowModal(!showModal)}
      >
        <Text size={30}>{selectedEmoji.char}</Text>
      </TouchableOpacity>
      <SwipeableModal
        isVisible={showModal}
        onClose={() => setShowModal(!showModal)}
      >
          <FlatList
            data={emojis}
            renderItem={({ item }) => renderEmoji(item)}
            horizontal={false}
            numColumns={6}
            key={6}
            initialNumToRender={5}
            maxToRenderPerBatch={10}
            removeClippedSubviews={true}
            keyExtractor={(item) => item.codes}
          />
      </SwipeableModal>
    </>
  );
};

如何提高性能并删除警告?

    • 更新**:

我通过将所有TouchableOpacity元素从react-native替换为Pressable,消除了第一个警告(挂起的回调过多)。这是一个已知问题:Github Issue

ozxc1zmp

ozxc1zmp1#

你应该考虑为你的表情创建一个专用的纯组件。纯组件在其属性没有改变时不会重新呈现。当组件依赖于它在列表中的位置而不是任何外部值时,这在列表中特别有用。如果你想了解更多信息,请参阅本指南:https://beta.reactjs.org/reference/react/PureComponent#migrating-from-a-purecomponent-class-component-to-a-function

import { memo } from 'react';

const Emoji = memo(({ emoji }) => {
  return (
    <TouchableOpacity
      onPress={() => {
        setSelectedEmoji(emoji);
        setShowModal(!showModal);
      }}
    >
      <Text style={styles.emoji} size={30}>
        {emoji.char}
      </Text>
    </TouchableOpacity>
  );
});

// ...

<FlatList
  data={emojis}
  renderItem={({ item }) => <Emoji emoji={item} />}
  // ...
/>

注意:因为内部组件不会在父状态(showModal)的每次更改时都重新呈现,所以onPress回调将保持其原始定义。在您的情况下,这可能是个问题,也可能不是,但我建议您使用“setState”函数的updater回调:

onPress={() => {
  setSelectedEmoji(emoji);
  setShowModal(wasShowingModal => !wasShowingModal);
}}
// The callback given to setShowModal will be invoked with
// the previous state at the time of the call, and not the
// value at the time the onPress callback is defined.

相关问题