refactor: Optimize message handling and event management

- Introduce messagesRef to track messages without causing re-renders
- Simplify event listener management with more concise useEffect hooks
- Improve auto-rename topic logic with current messages reference
- Remove commented-out code and unused event listeners
- Enhance type safety and reduce dependency complexity
This commit is contained in:
kangfenmao 2025-03-08 20:45:28 +08:00
parent 49d29d78da
commit 3312befe11
2 changed files with 46 additions and 30 deletions

View File

@ -50,6 +50,12 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
const [hasMore, setHasMore] = useState(false)
const [isLoadingMore, setIsLoadingMore] = useState(false)
const messagesRef = useRef<Message[]>([])
useEffect(() => {
messagesRef.current = messages
}, [messages])
useEffect(() => {
const reversedMessages = [...messages].reverse()
const newDisplayMessages = reversedMessages.slice(0, displayCount)
@ -85,15 +91,8 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
setTimeout(() => containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'auto' }), 50)
}, [])
// const onAppendMessageMemo = useCallback(
// async (message: Message) => {
// const newMessages = [...messages, message]
// await dispatch(updateMessages(topic, newMessages))
// },
// [topic, dispatch, messages]
// )
const autoRenameTopicMemo = useCallback(async () => {
const autoRenameTopic = useCallback(async () => {
const messages = messagesRef.current
const _topic = getTopic(assistant, topic.id)
if (!enableTopicNaming) {
@ -114,18 +113,16 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
updateTopic(data)
}
}
}, [assistant, enableTopicNaming, messages, setActiveTopic, topic.id, updateTopic, t])
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [assistant, topic.id, enableTopicNaming, t, setActiveTopic])
useEffect(() => {
const messages = messagesRef.current
const unsubscribes = [
// EventEmitter.on(EVENT_NAMES.APPEND_MESSAGE, onAppendMessageMemo),
// EventEmitter.on(EVENT_NAMES.RECEIVE_MESSAGE, () => {
// setTimeout(() => EventEmitter.emit(EVENT_NAMES.AI_AUTO_RENAME), 100)
// }),
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, () => {
scrollToBottom()
}),
EventEmitter.on(EVENT_NAMES.AI_AUTO_RENAME, autoRenameTopicMemo),
EventEmitter.on(EVENT_NAMES.CLEAR_MESSAGES, async (data: Topic) => {
const defaultTopic = getDefaultTopic(assistant.id)
@ -172,12 +169,13 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic })
})
]
return () => {
for (const unsub of unsubscribes) {
unsub()
}
}
}, [assistant, autoRenameTopicMemo, dispatch, messages, handleDeleteMessage, scrollToBottom, topic, updateTopic])
return () => unsubscribes.forEach((unsub) => unsub())
}, [assistant, dispatch, handleDeleteMessage, scrollToBottom, topic, updateTopic])
useEffect(() => {
const unsubscribes = [EventEmitter.on(EVENT_NAMES.AI_AUTO_RENAME, autoRenameTopic)]
return () => unsubscribes.forEach((unsub) => unsub())
}, [autoRenameTopic])
useEffect(() => {
runAsyncFunction(async () => {

View File

@ -172,9 +172,13 @@ export const {
const handleResponseMessageUpdate = (message, topicId, dispatch, getState) => {
dispatch(setStreamMessage({ topicId, message }))
// When message is complete, commit to messages and sync with DB
if (message.status !== 'pending') {
if (message.status === 'success') {
EventEmitter.emit(EVENT_NAMES.AI_AUTO_RENAME)
}
dispatch(commitStreamMessage({ topicId, messageId: message.id }))
const state = getState()
@ -225,7 +229,7 @@ export const sendMessage =
// 使用用户消息
let userMessage: Message
if (isResend) {
userMessage = options.resendUserMessage
userMessage = options.resendUserMessage!
} else {
// 创建新的用户消息
userMessage = getUserMessage({ assistant, topic, type: 'text', content })
@ -233,9 +237,11 @@ export const sendMessage =
if (options?.files) {
userMessage.files = options.files
}
if (options?.knowledgeBaseIds) {
userMessage.knowledgeBaseIds = options.knowledgeBaseIds
}
if (options?.mentionModels) {
userMessage.mentions = options.mentionModels
}
@ -245,6 +251,7 @@ export const sendMessage =
if (!isResend) {
dispatch(addMessage({ topicId: topic.id, messages: userMessage }))
}
EventEmitter.emit(EVENT_NAMES.SEND_MESSAGE)
// 处理助手消息
@ -284,8 +291,12 @@ export const sendMessage =
// Use topic queue to handle request
const queue = getTopicQueue(topic.id)
// let assistantMessage: Message | undefined
!isResend && dispatch(addMessage({ topicId: topic.id, messages: assistantMessages }))
if (!isResend) {
dispatch(addMessage({ topicId: topic.id, messages: assistantMessages }))
}
for (const assistantMessage of assistantMessages) {
// console.log('assistantMessage', assistantMessage)
@ -295,9 +306,11 @@ export const sendMessage =
// Sync user message with database
const state = getState()
const currentTopicMessages = state.messages.messagesByTopic[topic.id]
if (currentTopicMessages) {
await syncMessagesWithDB(topic.id, currentTopicMessages)
}
queue.add(async () => {
try {
const state = getState()
@ -340,7 +353,7 @@ export const sendMessage =
throttledDispatch({ ...assistantMessage, ...updatedMsg }, topic.id, dispatch, getState)
}
})
} catch (error) {
} catch (error: any) {
console.error('Error in chat completion:', error)
dispatch(
updateMessage({
@ -354,7 +367,7 @@ export const sendMessage =
}
})
}
} catch (error) {
} catch (error: any) {
console.error('Error in sendMessage:', error)
dispatch(setError(error.message))
} finally {
@ -409,7 +422,7 @@ export const resendMessage =
resendAssistantMessage: message
})
)
} catch (error) {
} catch (error: any) {
console.error('Error in resendMessage:', error)
dispatch(setError(error.message))
} finally {
@ -477,7 +490,10 @@ export const selectTopicMessages = createSelector(
[(state: RootState) => state.messages, (_, topicId: string) => topicId],
(messagesState, topicId) => {
const topicMessages = messagesState.messagesByTopic[topicId]
if (!topicMessages) return []
if (!topicMessages) {
return []
}
return [...topicMessages].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())
}
@ -503,7 +519,9 @@ export const selectError = (state: RootState): string | null => {
return messagesState?.error || null
}
export const selectStreamMessage = (state: RootState, topicId: string, messageId: string): Message | null =>
state.messages.streamMessagesByTopic[topicId]?.[messageId] || null
export const selectStreamMessage = (state: RootState, topicId: string, messageId: string): Message | null => {
const messagesState = state.messages as MessagesState
return messagesState.streamMessagesByTopic[topicId]?.[messageId] || null
}
export default messagesSlice.reducer