From 082909f3d6a04c7bc7dabb18079fd0e5718ae0ca Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 31 Oct 2021 16:03:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BD=93=E4=B8=8A=E6=BB=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=8E=86=E5=8F=B2=E6=B6=88=E6=81=AF=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E9=94=81=E5=AE=9A=E6=BB=9A=E5=8A=A8=E6=9D=A1=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/hooks/usePrevious.ts | 11 ++++++ shared/index.tsx | 1 + .../ChatMessageList/VirtualizedList.tsx | 38 ++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 shared/hooks/usePrevious.ts diff --git a/shared/hooks/usePrevious.ts b/shared/hooks/usePrevious.ts new file mode 100644 index 00000000..22b42277 --- /dev/null +++ b/shared/hooks/usePrevious.ts @@ -0,0 +1,11 @@ +import { useEffect, useRef } from 'react'; + +export function usePrevious(state: T): T | undefined { + const ref = useRef(); + + useEffect(() => { + ref.current = state; + }); + + return ref.current; +} diff --git a/shared/index.tsx b/shared/index.tsx index f560671d..bf3340db 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -53,6 +53,7 @@ export { useAsyncFn } from './hooks/useAsyncFn'; export { useAsyncRequest } from './hooks/useAsyncRequest'; export { useDebounce } from './hooks/useDebounce'; export { useMountedState } from './hooks/useMountedState'; +export { usePrevious } from './hooks/usePrevious'; export { useRafState } from './hooks/useRafState'; export { useUpdateRef } from './hooks/useUpdateRef'; diff --git a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx index 96f3a965..c9b72ee9 100644 --- a/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx +++ b/web/src/components/ChatBox/ChatMessageList/VirtualizedList.tsx @@ -2,13 +2,20 @@ import DynamicSizeList, { OnScrollInfo, } from '@/components/DynamicVirtualizedList/DynamicSizeList'; import { Divider } from 'antd'; -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, +} from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; import { ChatMessage, getMessageTimeDiff, shouldShowMessageTime, t, + usePrevious, useUpdateRef, } from 'tailchat-shared'; import { messageReverseItemId } from './const'; @@ -51,6 +58,7 @@ export const VirtualizedMessageList: React.FC = const listRef = useRef(null); const postListRef = useRef(null); const [isBottom, setIsBottom] = useState(true); + useLockScroll(props.messages, listRef); const handleScroll = (info: OnScrollInfo) => { const { @@ -110,7 +118,7 @@ export const VirtualizedMessageList: React.FC = /** * 渲染列表元素 */ - const renderRow = ({ data, itemId }: any) => { + const renderRow = ({ itemId }: any) => { if (itemId === messageReverseItemId.OLDER_MESSAGES_LOADER) { return (
@@ -208,3 +216,29 @@ export const VirtualizedMessageList: React.FC = ); }); VirtualizedMessageList.displayName = 'VirtualizedMessageList'; + +/** + * 当增加历史信息时锁定滚动条位置 + */ +function useLockScroll( + messages: ChatMessage[], + listRef: React.RefObject +) { + const previousMessages = usePrevious(messages); + const previousScrollHeight = usePrevious( + listRef.current?._outerRef?.scrollHeight + ); + useLayoutEffect(() => { + if (previousMessages && messages[0]._id !== previousMessages[0]._id) { + // 增加了历史消息 + if (listRef.current?._outerRef) { + // 能够拿到容器 + listRef.current.scrollTo( + listRef.current._outerRef.scrollTop + + listRef.current._outerRef.scrollHeight - + (previousScrollHeight || 0) + ); + } + } + }, [messages.length, previousMessages?.length]); +}