我有以下简化版本的 FlatList,它每 5 秒向其数据添加一个唯一项。
import React, {useState, useEffect, useMemo} from 'react';
import {SafeAreaView, Text, FlatList, ListRenderItem} from 'react-native';
interface LogMessage {
message: string;
}
const LogElement = (props: LogMessage) => {
return useMemo(() => {
return <Text>{props.message}</Text>;
}, [props.message]);
};
const FlatListRendersTooMuch = () => {
const [flatListContents, setFlatListContents] = useState([] as LogMessage[]);
useEffect(() => {
console.log('mounting');
const id = setInterval(() => {
console.log('adding new message');
setFlatListContents(f =>
f.concat({
message: new Date().toString(),
}),
);
}, 5000);
return () => {
console.log('unmounting');
clearInterval(id);
};
}, []);
const keyExtractor = (item: LogMessage) => {
return item.message;
};
const renderItem: ListRenderItem<LogMessage> = ({item}) => {
console.log('renderItemMemoFucntion ' + item.message);
return <LogElement {...item} />;
};
const renderItemMemoized = useMemo(() => renderItem, []);
return useMemo(() => {
return (
<SafeAreaView>
<FlatList
style={{height: 150, paddingTop: 10}}
data={flatListContents}
renderItem={renderItemMemoized}
keyExtractor={keyExtractor}
/>
</SafeAreaView>
);
}, [flatListContents, renderItemMemoized]);
};
我相信这遵循了最佳 FlatList 性能的最佳实践:
- 提供密钥提取器
- 记忆渲染项 JSX 函数
- 记忆渲染项功能本身
但是,该列表呈现的内容超出了预期(如 renderItem 方法中的日志语句所示)。例如,这是将第一个元素添加到列表时的输出:
adding new message
renderItemMemoFucntion Wed Apr 14 2021 16:56:13 GMT-0500 (Central Daylight Time)
这是添加第二条消息时的输出:
adding new message
renderItemMemoFucntion Wed Apr 14 2021 16:56:13 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:18 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:13 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:18 GMT-0500 (Central Daylight Time)
这是添加第三条消息时的输出:
adding new message
renderItemMemoFucntion Wed Apr 14 2021 16:56:13 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:18 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:23 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:13 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:18 GMT-0500 (Central Daylight Time)
renderItemMemoFucntion Wed Apr 14 2021 16:56:23 GMT-0500 (Central Daylight Time)
我的期望是,由于我记住了渲染函数,这将导致 renderItemMemoFunction 仅被添加到 FlatList 中的新元素调用。为什么这不会发生?