From 6cce254a58a680dd669262b2fd136b206e316d41 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Wed, 27 Oct 2021 12:33:58 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E8=99=9A=E6=8B=9F=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B9=B6=E5=A4=84=E7=90=86=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=B7=B2=E8=AF=BB=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChatMessageList/VirtualizedList.tsx | 52 ++++++++++--------- .../DynamicSizeList.tsx | 15 ++++-- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx index dd023500..1e6df3b7 100644 --- a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx +++ b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx @@ -2,12 +2,13 @@ import DynamicSizeList, { OnScrollInfo, } from '@/components/DynamicVirtualizedList/DynamicSizeList'; import { Divider } from 'antd'; -import React, { useRef, useState } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; import { ChatMessage, getMessageTimeDiff, shouldShowMessageTime, + useUpdateRef, } from 'tailchat-shared'; import { ChatMessageItem } from './Item'; @@ -37,22 +38,38 @@ function findMessageIndexWithId( interface VirtualizedMessageListProps { messages: ChatMessage[]; + onUpdateReadedMessage: (lastMessageId: string) => void; } export const VirtualizedMessageList: React.FC = React.memo((props) => { const listRef = useRef(null); - const postListRef = useRef(null); + const postListRef = useRef(null); const [isBottom, setIsBottom] = useState(true); const onScroll = (info: OnScrollInfo) => { - console.log('onScroll', info); - if (info.clientHeight + info.scrollOffset === info.scrollHeight) { // 当前滚动条位于底部 setIsBottom(true); + props.onUpdateReadedMessage( + props.messages[props.messages.length - 1]._id + ); } }; + const onUpdateReadedMessageRef = useUpdateRef(props.onUpdateReadedMessage); + useEffect(() => { + if (props.messages.length === 0) { + return; + } + + if (postListRef.current?.scrollTop === 0) { + // 当前列表在最低 + onUpdateReadedMessageRef.current( + props.messages[props.messages.length - 1]._id + ); + } + }, [props.messages.length]); + const initScrollToIndex = () => { return { index: 0, @@ -60,20 +77,9 @@ export const VirtualizedMessageList: React.FC = }; }; - const onItemsRendered = ({ visibleStartIndex }: any) => { - // this.updateFloatingTimestamp(visibleStartIndex); - console.log('visibleStartIndex', visibleStartIndex); - }; - - const scrollToFailed = (index: number) => { - console.log('scrollToFailed', index); - // if (index === 0) { - // this.props.actions.changeUnreadChunkTimeStamp(''); - // } else { - // this.props.actions.changeUnreadChunkTimeStamp(this.props.lastViewedAt); - // } - }; - + /** + * 渲染列表元素 + */ const renderRow = ({ data, itemId }: any) => { const messages = props.messages; const index = findMessageIndexWithId(messages, itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回,可以看看是否可以优化 @@ -119,10 +125,10 @@ export const VirtualizedMessageList: React.FC = }; // 初始渲染范围 - const initRangeToRender = [ - props.messages.length - 50, - props.messages.length - 1, - ]; + const initRangeToRender = useMemo( + () => [props.messages.length - 50, props.messages.length - 1], + [] + ); return ( @@ -143,8 +149,6 @@ export const VirtualizedMessageList: React.FC = initRangeToRender={initRangeToRender} // loaderId={PostListRowListIds.OLDER_MESSAGES_LOADER} correctScrollToBottom={isBottom} - onItemsRendered={onItemsRendered} - scrollToFailed={scrollToFailed} > {renderRow} diff --git a/web/src/components/DynamicVirtualizedList/DynamicSizeList.tsx b/web/src/components/DynamicVirtualizedList/DynamicSizeList.tsx index caef18d5..4de7a487 100644 --- a/web/src/components/DynamicVirtualizedList/DynamicSizeList.tsx +++ b/web/src/components/DynamicVirtualizedList/DynamicSizeList.tsx @@ -145,9 +145,9 @@ interface DynamicSizeListProps { initRangeToRender: number[]; initScrollToIndex: () => any; initialScrollOffset?: number; - innerRef: React.RefObject; + innerRef: React.RefObject; itemData: string[]; - onItemsRendered: (args: any) => void; + onItemsRendered?: (args: any) => void; onScroll: (scrollArgs: OnScrollInfo) => void; overscanCountBackward: number; overscanCountForward: number; @@ -377,7 +377,11 @@ export default class DynamicSizeList extends PureComponent< this._dataChange(); // though this is not data change we are checking for first load change } - if (prevProps.width !== this.props.width && !!this.props.innerRef) { + if ( + prevProps.width !== this.props.width && + !!this.props.innerRef && + !!this.props.innerRef.current + ) { this.innerRefWidth = this.props.innerRef.current.clientWidth; this._widthChange(prevProps.height, prevState.scrollOffset); } @@ -895,7 +899,12 @@ export default class DynamicSizeList extends PureComponent< }; _outerRefSetter = (ref: any) => { + if (!this.props.innerRef.current) { + return; + } + const { outerRef } = this.props; + this.innerRefWidth = this.props.innerRef.current.clientWidth; this._outerRef = ref;