简体   繁体   English

React Native - FlatLists 重新呈现记忆化组件(React.memo 不起作用)

[英]React Native - FlatLists re-renders memoized components (React.memo not working)

Main Problem主要问题

My FlatList ignores the children components memoizations.我的 FlatList 忽略子组件记忆。

Explanation解释

I have implemented a custom Component "Grid", which just renders the given data in a FlatList with a Grid layout.我已经实现了一个自定义组件“网格”,它只是在具有网格布局的 FlatList 中呈现给定的数据。

Here is the code:这是代码:

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}
    />
  );
}

Also, I have a top level component, which just renders my memoized component inside my custom Grid component, using a custom renderItem function:此外,我有一个顶级组件,它使用自定义 renderItem 函数在我的自定义 Grid 组件中呈现我的记忆化组件:

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}
    />
  );
}

The thing is, that for some reason, my memoized components which are returned from the renderItem function, are magically re-rendered when the data prop changes.问题是,由于某种原因,我从 renderItem 函数返回的记忆化组件会在数据道具更改时神奇地重新渲染。

For example, if I add a new element to my current data list, the FlatList will re-render all of its items.例如,如果我向当前数据列表添加一个新元素,则 FlatList 将重新呈现其所有项目。

Here is my memoized component:这是我的记忆组件:

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);

As you can see, my areEqual method returns true , so I suppose the error is in one of the parent components (Grid or UserPostsGrid).如您所见,我的 areEqual 方法返回 true ,因此我认为错误出在父组件之一(Grid 或 UserPostsGrid)中。

Any ideas about what am I doing wrong?关于我做错了什么的任何想法?

Note笔记

After modifying the data prop (state in a parent) from修改数据道具(父级中的状态)后

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

to

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

I get this in the console:我在控制台中得到这个:

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

THE ARE EQUAL FUNCTION IS NOT BEING EXECUTED!!!!!!没有执行相同的功能!!!!!!

Okey, the problem is with numColumns > 1.好吧,问题在于 numColumns > 1。

Because of Virtualization, my components are being re-mounted , not re-rendered.由于虚拟化,我的组件正在重新安装,而不是重新渲染。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 React 的 Context API 重新渲染所有包装在 Context 中的组件,即使使用了 React.Memo API - React's Context API re-renders all components that are wrapped inside the Context even after using the React.Memo API React.memo 不阻止重新渲染不接受任何道具的无状态功能子组件 - React.memo Not Preventing Re-renders of Stateless Functional Child Component that Takes In No Props 嵌套组件中的 React.memo 从不调用 areEqual,总是重新渲染 - React.memo inside nested component never calls areEqual, always re-renders 使用 React.memo() 记忆的组件不断重新渲染 - Component memoized with React.memo() keeps re-rendering 为什么 React 会重新渲染不必要的子组件,有时甚至是记忆化的组件? - Why React re-renders unnecessarily child components, sometimes even memoized ones? React.memo() 的第二个参数在 React Native 中无法正常工作 - Second arugument of React.memo() not working properly in react native 如果 props 改变,React.memo 不会重新渲染 - React.memo not re render if props change React router render prop路径总是重新渲染组件 - React router render prop route always re-renders components 自定义 React Hook 是否应该导致依赖组件的重新渲染? - Should Custom React Hooks Cause Re-Renders of Dependent Components? 3 state 的 React Native 许多重新渲染错误 - React Native many re-renders error for 3 state
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM