From dbee2437e7b6cceb6b4fcbdcbf0422a55293ebb7 Mon Sep 17 00:00:00 2001 From: chaos <1585767724@qq.com> Date: Fri, 30 Aug 2024 10:13:26 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20fix:=20chatList?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=8E=E6=BB=91=E5=8A=A8=E5=88=B0=E5=BA=95?= =?UTF-8?q?=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ProChat/index.tsx | 12 ++++++++++++ src/hooks/useChatList.ts | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/components/ProChat/index.tsx b/src/components/ProChat/index.tsx index ba91b66..36b0a0f 100644 --- a/src/components/ProChat/index.tsx +++ b/src/components/ProChat/index.tsx @@ -458,6 +458,18 @@ export function ProChat< } }, [loadingMessage]); + useEffect(() => { + if (chatListContainerRef.current) { + setTimeout(() => { + chatListContainerRef.current.scrollTo({ + behavior: 'smooth', + left: 0, + top: chatListContainerRef.current.scrollHeight, + }); + }, 0); + } + }, [chatList]); + const backBottomDom = useMemo(() => { if (!isInitRender) return null; return ( diff --git a/src/hooks/useChatList.ts b/src/hooks/useChatList.ts index 82343f8..91a8436 100644 --- a/src/hooks/useChatList.ts +++ b/src/hooks/useChatList.ts @@ -198,7 +198,8 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { */ const sendMessage = useRefFunction(async (message: string | Partial) => { controller.current = new AbortController(); - chatList.push( + setChatList((prevState) => [ + ...prevState, genMessageRecord( typeof message === 'string' ? { content: message } @@ -208,8 +209,7 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { }, 'user', ), - ); - setChatList([...chatList]); + ]); if (!props?.sendMessageRequest) return; setLoadingMessage( genMessageRecord( From e3eeb3b4e05613c7ac6968874beec83c3a516449 Mon Sep 17 00:00:00 2001 From: chaos <1585767724@qq.com> Date: Sun, 1 Sep 2024 22:23:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20fix:=20=E7=AE=80?= =?UTF-8?q?=E5=8C=96chatlist=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ChatList/index.tsx | 31 -------- src/components/ProChat/index.tsx | 20 +---- src/hooks/useChatList.ts | 122 ++++++++++++------------------ 3 files changed, 50 insertions(+), 123 deletions(-) diff --git a/src/components/ChatList/index.tsx b/src/components/ChatList/index.tsx index cb2a02f..776ce3b 100644 --- a/src/components/ChatList/index.tsx +++ b/src/components/ChatList/index.tsx @@ -16,7 +16,6 @@ import { useStyle } from './style'; export type ChatListProps = { chatList: ChatMessage[]; chatListRef: MutableRefObject; - loadingMessage?: ChatMessage; loading: boolean; className?: string; chatItemRenderConfig: ChatItemProps['chatItemRenderConfig']; @@ -50,7 +49,6 @@ const ChatList: React.FC = (props) => { chatListItemAvatarClassName, chatListItemContentClassName, chatListItemTitleClassName, - loadingMessage, userMeta = { avatar: DEFAULT_USER_AVATAR, }, @@ -104,35 +102,6 @@ const ChatList: React.FC = (props) => { ); })} - {loadingMessage && ( - - - - )} , ); }; diff --git a/src/components/ProChat/index.tsx b/src/components/ProChat/index.tsx index 36b0a0f..092dce7 100644 --- a/src/components/ProChat/index.tsx +++ b/src/components/ProChat/index.tsx @@ -378,8 +378,8 @@ export function ProChat< const { chatList, - loadingMessage, loading, + isLoadingMessage, setMessageItem, stopGenerateMessage, clearMessage, @@ -410,8 +410,6 @@ export function ProChat< : undefined, }); - const getChatLoadingMessage = useRefFunction(() => loadingMessage); - const getChatList = useRefFunction(() => { return chatList; }); @@ -422,7 +420,6 @@ export function ProChat< clearMessage, sendMessage, getChatList, - getChatLoadingMessage, setMessageItem, genMessageRecord, scrollToBottom: () => { @@ -456,18 +453,6 @@ export function ProChat< top: chatListContainerRef.current.scrollHeight, }); } - }, [loadingMessage]); - - useEffect(() => { - if (chatListContainerRef.current) { - setTimeout(() => { - chatListContainerRef.current.scrollTo({ - behavior: 'smooth', - left: 0, - top: chatListContainerRef.current.scrollHeight, - }); - }, 0); - } }, [chatList]); const backBottomDom = useMemo(() => { @@ -509,7 +494,6 @@ export function ProChat< userMeta={userMeta} assistantMeta={assistantMeta} loading={loading} - loadingMessage={loadingMessage} chatItemRenderConfig={chatItemRenderConfig} style={{ ...styles?.chatList, @@ -532,7 +516,7 @@ export function ProChat< {backBottomDom} { let controller = useRef(null); - const loadingMessageRef = useRef | undefined>(undefined); - - const [loadingMessage, setLoadingMessage] = useMergedState | undefined>( - undefined, - { - postState: (value) => { - loadingMessageRef.current = value; - return value; - }, - }, - ); - - const getLoadingMessage = useRefFunction(() => { - return loadingMessageRef.current; - }); - const chatListRef = useRef[]>([]); /** * Custom hook for managing the chat list. @@ -144,7 +128,7 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { const [loading, setLoading] = useMergedState(true, { value: props.loading, }); - + const [isLoadingMessage, setIsLoadingMessage] = useMergedState(false); /** * Fetches the chat list using the provided request function. * If the request function is not provided, it sets the loading state to false and returns. @@ -198,6 +182,7 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { */ const sendMessage = useRefFunction(async (message: string | Partial) => { controller.current = new AbortController(); + setChatList((prevState) => [ ...prevState, genMessageRecord( @@ -210,20 +195,23 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { 'user', ), ]); + if (!props?.sendMessageRequest) return; - setLoadingMessage( + setIsLoadingMessage(true); + setChatList((prevState) => [ + ...prevState, genMessageRecord( { content: LOADING_FLAT, }, 'assistant', ), - ); + ]); const res = (await Promise.race([ props.sendMessageRequest?.(chatListRef.current), new Promise((_, reject) => { - controller.current.signal.addEventListener('abort', () => { + controller.current?.signal.addEventListener('abort', () => { reject(); }); }), @@ -233,75 +221,61 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { processSSE(res, { signal: controller.current.signal, onFinish: async () => { - setLoadingMessage(undefined); + setChatList((prevState) => { + const updatedList = [...prevState]; + updatedList[updatedList.length - 1].isFinished = true; + return updatedList; + }); + setIsLoadingMessage(false); }, onMessageHandle: async (text, res, type) => { - if (type === 'done' || controller.current.signal.aborted) { - const message = getLoadingMessage(); - if (!message) return; - setChatList((prev) => { - message.isFinished = true; - return [...prev, message]; + if (type === 'done' || controller.current?.signal.aborted) { + setIsLoadingMessage(false); + setChatList((prevState) => { + const updatedList = [...prevState]; + updatedList[updatedList.length - 1].isFinished = true; + return updatedList; }); - setLoadingMessage(undefined); return; } - const content = - getLoadingMessage()?.content === LOADING_FLAT - ? text - : getLoadingMessage()?.content + text; - const message: ChatMessage = { - ...getLoadingMessage(), - updateAt: Date.now(), - originContent: text, - isFinished: false, - content: content, - }; - const transformMessage = await props.transformToChatMessage?.(message, { - preContent: - getLoadingMessage()?.content === LOADING_FLAT ? '' : getLoadingMessage()?.content, - currentContent: text, + setChatList((prevState) => { + const updatedList = [...prevState]; + const currentMessage = updatedList[updatedList.length - 1]; + currentMessage.content = + currentMessage.content === LOADING_FLAT ? text : currentMessage.content + text; + currentMessage.updateAt = Date.now(); + return updatedList; }); - - loadingMessageRef.current = transformMessage || message; - setLoadingMessage(transformMessage || message); }, onErrorHandle: async (error) => { const content = error.message; - const message = await props.transformToChatMessage?.( - { - ...getLoadingMessage(), - updateAt: Date.now(), - content: content, - originContent: content, - }, - { - preContent: getLoadingMessage()?.content, - currentContent: content, - }, - ); - setLoadingMessage(undefined); - setChatList((prev) => [...prev, message]); + setChatList((prevState) => { + const updatedList = [...prevState]; + const currentMessage = updatedList[updatedList.length - 1]; + currentMessage.content = content; + currentMessage.originContent = content; + currentMessage.updateAt = Date.now(); + currentMessage.isFinished = true; + return updatedList; + }); + setIsLoadingMessage(false); }, }); } else { - const message = { - ...getLoadingMessage(), - updateAt: Date.now(), - ...res, - }; - - const transformChatMessage = await props.transformToChatMessage?.(message, { - preContent: getLoadingMessage()?.content, - currentContent: message.originContent, + setChatList((prevState) => { + const updatedList = [...prevState]; + const currentMessage = { + ...updatedList[updatedList.length - 1], + ...res, + updateAt: Date.now(), + }; + updatedList[updatedList.length - 1] = currentMessage; + return updatedList; }); - - setLoadingMessage(undefined); - setChatList((prev) => [...prev, transformChatMessage || message]); + setIsLoadingMessage(false); } }); - /** * Stops the generation of messages. */ @@ -330,7 +304,7 @@ export const useChatList = (props: ProChatUIUseListChatProps) => { return { chatList: chatList.length > 0 ? chatList : helloMessageList, loading, - loadingMessage, + isLoadingMessage, stopGenerateMessage, setMessageItem, clearMessage,