[英]React Native - FlatLists re-renders memoized components (React.memo not working)
My FlatList ignores the children components memoizations.我的 FlatList 忽略子组件记忆。
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?关于我做错了什么的任何想法?
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.