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

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

@ -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<VirtualizedMessageListProps> =
React.memo((props) => {
const listRef = useRef<DynamicSizeList>(null);
const postListRef = useRef<any>(null);
const postListRef = useRef<HTMLDivElement>(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<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 messages = props.messages;
const index = findMessageIndexWithId(messages, itemId); // TODO: 这里是因为mattermost的动态列表传的id因此只能这边再用id找回可以看看是否可以优化
@ -119,10 +125,10 @@ export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
};
// 初始渲染范围
const initRangeToRender = [
props.messages.length - 50,
props.messages.length - 1,
];
const initRangeToRender = useMemo(
() => [props.messages.length - 50, props.messages.length - 1],
[]
);
return (
<AutoSizer>
@ -143,8 +149,6 @@ export const VirtualizedMessageList: React.FC<VirtualizedMessageListProps> =
initRangeToRender={initRangeToRender}
// loaderId={PostListRowListIds.OLDER_MESSAGES_LOADER}
correctScrollToBottom={isBottom}
onItemsRendered={onItemsRendered}
scrollToFailed={scrollToFailed}
>
{renderRow}
</DynamicSizeList>

@ -145,9 +145,9 @@ interface DynamicSizeListProps {
initRangeToRender: number[];
initScrollToIndex: () => any;
initialScrollOffset?: number;
innerRef: React.RefObject<any>;
innerRef: React.RefObject<HTMLDivElement>;
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;

Loading…
Cancel
Save