perf: 虚拟列表优化并处理消息已读情况

pull/13/head
moonrailgun 5 years ago
parent fcaa7e42f1
commit 6cce254a58

@ -2,12 +2,13 @@ import DynamicSizeList, {
OnScrollInfo, OnScrollInfo,
} from '@/components/DynamicVirtualizedList/DynamicSizeList'; } from '@/components/DynamicVirtualizedList/DynamicSizeList';
import { Divider } from 'antd'; 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 AutoSizer from 'react-virtualized-auto-sizer';
import { import {
ChatMessage, ChatMessage,
getMessageTimeDiff, getMessageTimeDiff,
shouldShowMessageTime, shouldShowMessageTime,
useUpdateRef,
} from 'tailchat-shared'; } from 'tailchat-shared';
import { ChatMessageItem } from './Item'; import { ChatMessageItem } from './Item';
@ -37,22 +38,38 @@ function findMessageIndexWithId(
interface VirtualizedMessageListProps { interface VirtualizedMessageListProps {
messages: ChatMessage[]; messages: ChatMessage[];
onUpdateReadedMessage: (lastMessageId: string) => void;
} }
export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> = export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
React.memo((props) => { React.memo((props) => {
const listRef = useRef<DynamicSizeList>(null); const listRef = useRef<DynamicSizeList>(null);
const postListRef = useRef<any>(null); const postListRef = useRef<HTMLDivElement>(null);
const [isBottom, setIsBottom] = useState(true); const [isBottom, setIsBottom] = useState(true);
const onScroll = (info: OnScrollInfo) => { const onScroll = (info: OnScrollInfo) => {
console.log('onScroll', info);
if (info.clientHeight + info.scrollOffset === info.scrollHeight) { if (info.clientHeight + info.scrollOffset === info.scrollHeight) {
// 当前滚动条位于底部 // 当前滚动条位于底部
setIsBottom(true); 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 = () => { const initScrollToIndex = () => {
return { return {
index: 0, index: 0,
@ -60,20 +77,9 @@ export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
}; };
}; };
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 renderRow = ({ data, itemId }: any) => {
const messages = props.messages; const messages = props.messages;
const index = findMessageIndexWithId(messages, itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回可以看看是否可以优化 const index = findMessageIndexWithId(messages, itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回可以看看是否可以优化
@ -119,10 +125,10 @@ export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
}; };
// 初始渲染范围 // 初始渲染范围
const initRangeToRender = [ const initRangeToRender = useMemo(
props.messages.length - 50, () => [props.messages.length - 50, props.messages.length - 1],
props.messages.length - 1, []
]; );
return ( return (
<AutoSizer> <AutoSizer>
@ -143,8 +149,6 @@ export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
initRangeToRender={initRangeToRender} initRangeToRender={initRangeToRender}
// loaderId={PostListRowListIds.OLDER_MESSAGES_LOADER} // loaderId={PostListRowListIds.OLDER_MESSAGES_LOADER}
correctScrollToBottom={isBottom} correctScrollToBottom={isBottom}
onItemsRendered={onItemsRendered}
scrollToFailed={scrollToFailed}
> >
{renderRow} {renderRow}
</DynamicSizeList> </DynamicSizeList>

@ -145,9 +145,9 @@ interface DynamicSizeListProps {
initRangeToRender: number[]; initRangeToRender: number[];
initScrollToIndex: () => any; initScrollToIndex: () => any;
initialScrollOffset?: number; initialScrollOffset?: number;
innerRef: React.RefObject<any>; innerRef: React.RefObject<HTMLDivElement>;
itemData: string[]; itemData: string[];
onItemsRendered: (args: any) => void; onItemsRendered?: (args: any) => void;
onScroll: (scrollArgs: OnScrollInfo) => void; onScroll: (scrollArgs: OnScrollInfo) => void;
overscanCountBackward: number; overscanCountBackward: number;
overscanCountForward: 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 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.innerRefWidth = this.props.innerRef.current.clientWidth;
this._widthChange(prevProps.height, prevState.scrollOffset); this._widthChange(prevProps.height, prevState.scrollOffset);
} }
@ -895,7 +899,12 @@ export default class DynamicSizeList extends PureComponent<
}; };
_outerRefSetter = (ref: any) => { _outerRefSetter = (ref: any) => {
if (!this.props.innerRef.current) {
return;
}
const { outerRef } = this.props; const { outerRef } = this.props;
this.innerRefWidth = this.props.innerRef.current.clientWidth; this.innerRefWidth = this.props.innerRef.current.clientWidth;
this._outerRef = ref; this._outerRef = ref;

Loading…
Cancel
Save