use-send-chat-message.ts
Overview
The use-send-chat-message.ts file provides React hooks that manage the complex logic of selecting, displaying, sending, and updating chat messages within a conversation context in a chat application. It integrates message state management, conversation fetching, message input handling, file upload support, and real-time streaming responses (via Server-Sent Events, SSE).
The primary exports are two custom hooks:
useSelectNextMessages: Manages the state and lifecycle of the current list of chat messages in the conversation, including initializing messages for new conversations.useSendMessage: Handles sending new messages, uploading files, regenerating AI responses, and updating the conversation state with server responses.
Together, these hooks encapsulate the key business logic needed to:
Load and display chat conversation messages.
Append assistant-generated prologue messages for new conversations.
Send user messages to the backend, including streamed AI responses.
Handle file uploads attached to messages.
Manage UI states like loading, input value, and scroll behavior.
Detailed Explanation
Imports and Dependencies
React hooks:
useCallback,useEffectuuid: Generates unique IDs for messages.Utility libraries:
lodash.trimfor input trimming.Custom hooks for fetching conversations, managing chat routes, message input handling, SSE message sending, file upload, and conversation selection.
Constants and interfaces for message types and structure.
API utility for backend interaction.
Exported Hooks
1. useSelectNextMessages()
Manages message selection, initialization, and updates for the current chat conversation.
Returns
An object containing:
scrollRef: React ref for the scroll container.
messageContainerRef: React ref for the message container.
derivedMessages: Array of current chat messages (
IMessage[]).loading: Boolean indicating if the conversation is loading.
addNewestAnswer(message: IMessage): Function to append a new assistant answer message.
addNewestQuestion(message: IMessage): Function to append a new user question message.
removeLatestMessage(): Function to remove the newest message.
removeMessageById(id: string): Function to remove a message by its ID.
removeMessagesAfterCurrentMessage(id: string): Removes all messages after a specific message ID.
Behavior and Implementation Details
Fetches the current conversation and chat parameters (
conversationId,isNew,dialogId).Retrieves a "prologue" message (an assistant introductory message) for new conversations.
On mount or when relevant params change:
If the conversation is new (
isNew === 'true'), sets the prologue message as the only message.Else, loads existing conversation messages into
derivedMessages.Clears messages if no
conversationIdexists.
Uses useSelectDerivedMessages() to handle message state and mutation functions.
Usage Example
const {
derivedMessages,
addNewestAnswer,
addNewestQuestion,
removeLatestMessage,
loading,
} = useSelectNextMessages();
useEffect(() => {
if (!loading) {
addNewestQuestion({ id: '123', content: 'Hello', role: MessageType.User });
}
}, [loading]);
2. useSendMessage(controller: AbortController)
Handles sending chat messages, file uploads, and regenerating responses with SSE.
Parameters
controller: AbortController— Controller to abort ongoing SSE requests if needed.
Returns
An object with:
handlePressEnter(): Called when user presses Enter to send a message.
handleInputChange(event): Handler for message input changes.
value: string: Current message input value.
setValue(newValue: string): Setter for input value.
regenerateMessage(): Function to regenerate the last assistant message.
sendLoading: boolean: Indicates if a message is currently being sent.
loading: boolean: Overall loading state.
scrollRef: Ref to scroll container.
messageContainerRef: Ref to message container.
derivedMessages: Current list of messages.
removeMessageById(id: string): Remove message by ID.
stopOutputMessage(): Aborts the ongoing message streaming.
handleUploadFile(files, options): Handler for file uploads.
isUploading: boolean: Upload status.
removeFile(id: string): Remove uploaded file by ID.
Key Implementation Details
Uses
useSetConversation,useGetChatSearchParams,useHandleMessageInputChange,useUploadFile, and other hooks to manage state and side effects.Uploads files attached to new messages. For new conversations, it first creates the conversation before uploading.
Sends messages via
useSendMessageWithSsehook, which performs SSE-based streaming of AI-generated answers.Supports aborting message streaming via
AbortController.Adds user messages and assistant answers to the message list with appropriate roles.
Handles regeneration of assistant responses by removing subsequent messages and resending.
On pressing Enter:
Validates input.
Adds a new user question message with a unique ID.
Sends the message if streaming is done.
Clears the file attachment list.
Usage Example
const controller = new AbortController();
const {
handlePressEnter,
handleInputChange,
value,
sendLoading,
stopOutputMessage,
} = useSendMessage(controller);
// Attach handleInputChange to input field
// Call handlePressEnter on Enter key press
Important Implementation Details and Algorithms
Message Prologue Injection: For new conversations (
isNew === 'true'), the assistant's "prologue" message is injected as the first message using auseCallbackwrapped function triggered on mount or dependency changes.Streaming Message Responses: Messages are sent using SSE (Server-Sent Events) via the
useSendMessageWithSsehook, allowing partial AI responses to be streamed and appended live.File Upload Integration: File uploads are handled with
useUploadFilehook. For new conversations, the conversation is initialized first, then files are uploaded with conversation ID association.State Synchronization: The hooks synchronize UI state (
derivedMessages, input value, loading states) with backend API responses and route parameters.AbortController Use: Enables stopping in-progress SSE streaming cleanly when needed (e.g., user cancels or navigates away).
Interaction with Other Parts of the System
API Layer: Uses
api.completeConversationfor sending messages and receiving AI-generated answers.Routing: Reads query parameters such as
conversationIdandisNewto determine conversation state.Chat UI Components: Interfaces with components such as message input, message list rendering, and file upload UI via returned handlers and state.
Hooks: Depends heavily on other internal hooks for fetching conversations, managing chat state, message mutation, and file uploads.
Database Interfaces: Utilizes
IMessageandMessageinterfaces for consistent message data structures.
Mermaid Diagram: Flowchart of Main Functions and Their Relationships
flowchart TD
A[useSelectNextMessages] --> B[Fetch conversation & params]
B --> C{isNew conversation?}
C -- Yes --> D[Add Prologue message]
C -- No --> E[Set messages from conversation]
F[useSendMessage] --> G[Handle input change & value]
F --> H[Handle file uploads]
F --> I[Send message with SSE]
F --> J[Add user question message]
F --> K[Add assistant answer message]
F --> L[Stop message streaming (abort)]
I --> M[API call: completeConversation]
H --> N[Upload files with conversation ID]
style A fill:#f9f,stroke:#333,stroke-width:1px
style F fill:#bbf,stroke:#333,stroke-width:1px
Summary
The use-send-chat-message.ts file encapsulates core chat message management and sending logic in React hooks for a conversational AI/chat application. It abstracts the complexity of message state, conversation lifecycle, SSE streaming, and file uploads, providing simple interfaces for UI components to interact with chat functionality efficiently and reliably.