我正在 React Native 中开发一个聊天应用程序,并面临在 FlatList 中渲染许多消息的问题。我想在列表底部显示最新消息,类似于 WhatsApp 和 Messenger 的工作方式。我尝试了多种方法,但没有一种方法能够提供我想要的流畅体验:
<FlatList
inverted
contentContainerStyle={{
flexGrow: 1,
flexDirection: 'column-reverse',
}}
ref={flatListRef}
data={chat}
keyExtractor={keyExtractor}
renderItem={renderMessage}
ItemSeparatorComponent={renderSeperator}
/>
ITEM_HEIGHT
不会固定,所以它会在最大消息中花费大量性能. <FlatList
ref={flatListRef}
data={chat}
keyExtractor={keyExtractor}
renderItem={renderMessage}
ItemSeparatorComponent={renderSeperator}
initialScrollIndex={chat.length - 1}
getItemLayout={(_, index) => {
return {length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index};
}}
/>
const scrollToBottom = (isAnimated = false) => {
if (flatListRef.current) {
flatListRef.current.scrollToEnd({animated: isAnimated});
}
};
return (
<FlatList
ref={flatListRef}
data={chat}
keyExtractor={keyExtractor}
renderItem={renderMessage}
ItemSeparatorComponent={renderSeperator}
onContentSizeChange={() => scrollToBottom(false)} // Doesn't matter if i use animated or not
/>
);
我正在寻找一种方法来优化 FlatList,即使有大量消息,也能立即显示最新消息,没有任何延迟。我愿意接受诸如在用户向上滚动时删除旧消息之类的建议,但我不确定如何有效地实现这一点。任何实现流畅聊天体验的指导或替代方法将不胜感激。
使用
inverted
道具,它起作用了。有一个简单的技巧,我也必须使用 reverse()
函数来反转消息数组,而且我还必须使用scrollToTop 函数才能滚动到底部。这是我制作聊天屏幕应用程序的方法,外观非常流畅。
const DUMMY_CHAT = new Array(10000).fill(null).map((_, i) => ({message: i.toString()}))
const flatListRef = useRef();
const [chat, setChat] = useState(DUMMY_CHAT);
const renderMessage = ({item, index}) => <ChatMsg {...item} />;
const renderSeperator = useCallback(() => <Spacer height={24} />, []);
const keyExtractor = useCallback((_, i) => i.toString(), []);
// This function will now actually scroll to the bottom.
// Now you can use this function suppose sending new message to scroll to the bottom.
const scrollToTop = (isAnimated = false) => {
if (flatListRef.current) {
flatListRef.current.scrollToOffset({offset: 0, animated: isAnimated});
}
};
return (
<FlatList
inverted
ref={flatListRef}
data={chat.reverse()}
istHeaderComponent={ChatInternalHeader}
keyExtractor={keyExtractor}
renderItem={renderMessage}
ItemSeparatorComponent={renderSeperator}
/>
);