在react native中不断向Flatlist添加元素,导致整个页面不断刷新

hkmswyz6  于 2023-10-22  发布在  React
关注(0)|答案(1)|浏览(156)

我目前正在Android上的一个react本地页面上工作,有一个要求,允许用户输入一些东西,并将其添加到一个列表中,最新的项目在顶部。我正在使用Flatlist来呈现这些文本,目前我遇到了性能问题。
在我父组件中:

const SomePage = () => {
  ...
  const [myArray, setMyArray] = useState<SomeType[]>([]);
  ...

  const addItem = (item) => {
    let newData = { id: item.id, desc: item.desc, index: someCounter };
    setMyArray([newData, ...myArray]);
  }

用于呈现平面列表中每个项目的代码:

const renderItemList = useCallback(
    ({item, index}, someFunction) => {
      const closeRow = (closeIndex: number) => {
        // close an item when another is opened
        if (
          prevOpenedRow.current &&
          prevOpenedRow.current !== row[closeIndex]
        ) {
          prevOpenedRow.current.close();
        }

        prevOpenedRow.current = row[closeIndex];
      };
      const renderRightActions = (progress, dragX, someFunction) => {
        const opacity = dragX.interpolate({
          inputRange: [-80, 0],
          outputRange: [1, 0],
          extrapolate: 'clamp',
        });
        return (
          <Animated.View style={[styles.swipedRow, {opacity}]}>
            <Animated.View style={styles.deleteButton}>
              <Pressable style={{alignItems: 'center'}} onPress={someFunction}>
                <SvgDelete />
                <Animated.Text style={styles.deleteButtonText}>
                  Delete
                </Animated.Text>
              </Pressable>
            </Animated.View>
          </Animated.View>
        );
      };

      return (
        <Swipeable
          key={item.id}
          overshootFriction={3}
          onSwipeableWillOpen={() => {
            someTextInputRef?.current?.blur();
          }}
          renderRightActions={(progress, dragX) =>
            renderRightActions(progress, dragX, onClick)
          }
          onSwipeableOpen={() => closeRow(index)}
          ref={ref => (row[index] = ref)}>
          <View>
            <View>
              <Text>#{item.index}</Text>
              <SvgDot /> // some image
              <Text>{item.id}</Text>
              <SvgDot /> // some image
              <SvgSealDot
                stroke={Colors.Black30}
              />
              <Text>ID</Text>
            </View>
            <Text>{item.desc}</Text>
          </View>
        </Swipeable>
      );
    },
    [row, myArray],
  );

  const someFunction = () => {
    ...
  }

呈现FlatList的代码:

return (
    <View>
      ...
        <FlatList
          showsVerticalScrollIndicator={true}
          data={myArray}
          renderItem={item =>
            renderItemList(item, () => {
              someFunction(item);
            })
          }
          keyExtractor={item => {
            return item.id.toString();
          }}
          removeClippedSubviews
        </FlatList>
      ... 
    </View>
  );
}

我注意到FlatList是此页面的一部分,如果此页面中有任何内容,则FlatList中的所有内容都将再次呈现,即使我为每个项目呈现使用useCallback
这是非常令人困惑的一部分,当我添加一个新的项目到数组中,首先页面重新呈现一次,因为一些 prop 改变

然后FlatList再次重新渲染,因为有一些新元素(所有元素都将重新渲染,这需要惊人的600 ms-1000 ms来重新渲染列表中的每个元素。列表中最多可能有200个项目
我能做些什么来防止这些东西重新渲染吗?我需要一个接一个地添加200个项目,每次插入列表都会导致页面重新渲染一次(包括FlatList中的所有内容),然后FlatList再次重新渲染所有内容。
我已经尝试了removeClippedSubviews,但它没有任何影响这个问题。
我也试过使用myArray.map(.一些useCallback函数来渲染),但一切仍然是重新渲染
只是寻找方法来停止一切从重新渲染,使应用程序可以添加到这个列表顺利一切

vshtjzan

vshtjzan1#

尝试使用BigList,这是React Native的高性能列表视图,支持复杂布局,使用类似的FlatList用法来简化替换。

示例

如果您有任何状态要在呈现器中使用,且您希望避免不必要重新呈现(在这种情况下),请使用usecallback

const renderItem = useCallback(({ item, index }: { item: any, index: number }) => {
  return (
    <View style={s.content}>
      
    </View>
  )
}, []); // add state dependency here

<BigList
    data={event}
    renderItem={renderItem}
    itemHeight={70}
  />

相关问题