【问题标题】:React Native - FlatLists re-renders memoized components (React.memo not working)React Native - FlatLists 重新渲染记忆组件(React.memo 不工作)
【发布时间】:2021-12-04 08:57:57
【问题描述】:

主要问题

我的 FlatList 忽略了子组件的记忆。

说明

我已经实现了一个自定义组件“网格”,它只是将给定的数据呈现在具有网格布局的 FlatList 中。

代码如下:

export default function Grid({
  data = [],
  keyExtractor,
  numColumns = 4,
  initialNumToRender,
  renderItem,
  itemMargin = StyleSheet.hairlineWidth,
  isLoading,
  onEndReachedThreshold = 0.5,
  onEndReached,
  ...props
}) {
  const renderGridItem = (item) => {
    const { index } = item;

    const { width } = Dimensions.get("window");

    const size = Math.floor(
      PixelRatio.roundToNearestPixel(
        (width - itemMargin * (numColumns - 1)) / numColumns
      )
    );

    // We don't want to include a `marginLeft` on the first item of a row
    const marginLeft = index % numColumns === 0 ? 0 : itemMargin;

    // We don't want to include a `marginTop` on the first row of the grid
    const marginTop = index < numColumns ? 0 : itemMargin;

    return renderItem({
      ...item,
      size,
      marginLeft,
      marginTop,
    });
  };

  const renderFooter = () => {
    if (!isLoading) return null;

    return (
      <View style={globalStyles.listFooter}>
        <Loading />
      </View>
    );
  };

  return (
    <FlatList
      {...props}
      data={data}
      keyExtractor={keyExtractor}
      numColumns={numColumns}
      initialNumToRender={initialNumToRender}
      renderItem={renderGridItem}
      ListFooterComponent={renderFooter}
      onEndReachedThreshold={onEndReachedThreshold}
      onEndReached={onEndReached}
      style={globalStyles.listContainer}
      contentContainerStyle={globalStyles.listContainer}
    />
  );
}

另外,我有一个顶级组件,它只是在我的自定义 Grid 组件中呈现我的 memoized 组件,使用自定义 renderItem 函数:

export default function UserPostsGrid({
  listKey,
  data = [],
  numColumns,
  initialNumToRender,
  itemMargin,
  isLoading,
  ListEmptyComponent,
  onEndReached,
  ...props
}) {
  const keyExtractor = useCallback(({ id }) => id, []);

  const renderItem = useCallback(
    ({ item, index, size, marginLeft, marginTop }) => {
      const style = {
        width: size,
        height: size,
        marginLeft,
        marginTop,
      };

      return <UserPostsGridItem item={item} index={index} style={style} />;
    },
    []
  );

  return (
    <Grid
      {...props}
      listKey={listKey}
      data={data}
      keyExtractor={keyExtractor}
      numColumns={numColumns}
      renderItem={renderItem}
      initialNumToRender={initialNumToRender}
      isLoading={isLoading}
      removeClippedSubviews={false}
      ListEmptyComponent={ListEmptyComponent}
      itemMargin={itemMargin}
      onEndReachedThreshold={0.5}
      onEndReached={onEndReached}
    />
  );
}

问题是,由于某种原因,我从 renderItem 函数返回的记忆化组件在 data prop 更改时会神奇地重新渲染。

例如,如果我在当前数据列表中添加一个新元素,FlatList 将重新渲染它的所有项目。

这是我的记忆组件:

function UserPostsGridItem({
  item: {
    index,
    images: [{ uri, thumbnailUri }],
  },
  style,
}) {
  const handleOnPress = () => {
    // TODO - Push card lists stack
    console.log(index);
  };

  console.log("Rerendering grid item!", uri);

  return (
    <TouchableOpacity activeOpacity={0.5} onPress={handleOnPress} style={style}>
      <Image
        uri={uri}
        thumbnailUri={thumbnailUri}
        imageFadeDuration={200}
        thumbnailFadeDuration={100}
        withLoading={false}
        style={globalStyles.flexContainer}
      />
    </TouchableOpacity>
  );
}

function areUserPostsGridItemPropsEqual() {
  console.log("Running areEqual"); // <---- NOTE THIS!
  return true;
}

export default memo(UserPostsGridItem, areUserPostsGridItemPropsEqual);

如您所见,我的 areEqual 方法返回 true,所以我认为错误出在父组件之一(Grid 或 UserPostsGrid)中。

关于我做错了什么有什么想法吗?

注意

修改数据道具(父级中的状态)后
 data=[{id: "1", ...}]

 data=[{id: "2", ...}, {id: "1", ...}]

我在控制台中得到了这个:

"Rerendering grid item! uri..."
"Rerendering grid item! uri..."

没有执行 ARE EQUAL 功能!!!!!!

【问题讨论】:

    标签: javascript reactjs react-native memoization


    【解决方案1】:

    好的,问题在于 numColumns > 1。

    由于虚拟化,我的组件被重新安装,而不是重新渲染。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      • 2019-09-26
      • 2018-12-27
      • 1970-01-01
      • 2018-12-16
      • 2019-02-26
      • 2021-11-16
      相关资源
      最近更新 更多