Optionalparams: UseMessagesParamsOptional parameters for event listeners and room status callbacks
A UseMessagesResponse containing message methods and room status
An Ably.ErrorInfo with ReactHookMustBeUsedWithinProvider When used outside of a ChatRoomProvider
import React, { useState } from 'react';
import { ChatClient, ChatMessageEventType, Message, ChatMessageEvent, MessageReactionSummaryEvent } from '@ably/chat';
import { ChatClientProvider, ChatRoomProvider, useMessages } from '@ably/chat/react';
// Helper function to update local message state
const updateLocalMessageState = (messages: Message[], message: Message): Message[] => {
// Find existing message in local state
const existingIndex = messages.findIndex(m => m.serial === message.serial);
let updatedMessages = [...messages];
if (existingIndex === -1) {
// New message, add to local state
updatedMessages.push(message);
} else {
// Update existing message using with() method
updatedMessages[existingIndex] = updatedMessages[existingIndex].with(message);
}
// Sort by serial for deterministic ordering
return updatedMessages.sort((a, b) => a.serial < b.serial ? -1 : (b.serial < a.serial ? 1 : 0));
};
// Component that handles messages
const MessageHandler = () => {
const [messages, setMessages] = useState<Message[]>([]);
const { sendMessage } = useMessages({
listener: (event: ChatMessageEvent) => {
console.log(`Message ${event.type}:`, event.message.text);
setMessages(prevMessages => {
switch (event.type) {
case ChatMessageEventType.Created:
case ChatMessageEventType.Updated:
case ChatMessageEventType.Deleted:
return updateLocalMessageState(prevMessages, event.message);
default:
return prevMessages;
}
});
},
reactionsListener: (event: MessageReactionSummaryEvent) => {
// Update message with new reaction data using with() method
setMessages(prevMessages => {
const messageIndex = prevMessages.findIndex(m => m.serial === event.messageSerial);
if (messageIndex === -1) {
// Message not found, return unchanged
return prevMessages;
}
// Update the specific message and return new array
const updatedMessages = [...prevMessages];
updatedMessages[messageIndex] = updatedMessages[messageIndex].with(event);
return updatedMessages;
});
},
onDiscontinuity: (error) => {
console.error('Discontinuity detected:', error);
// Clear local state and optionally re-fetch messages using historyBeforeSubscribe.
setMessages([]);
}
});
return (
<div>
{messages.map(message => (
<div key={message.serial}>
<strong>{message.clientId}:</strong> {message.isDeleted ? <em>Deleted Message</em>: message.text}
<div>
{Object.entries(message.reactions.unique).map(([reaction, summary]) => (
<span key={`unique-${reaction}`}>{reaction} {summary.total}</span>
))}
{Object.entries(message.reactions.distinct).map(([reaction, summary]) => (
<span key={`distinct-${reaction}`}>{reaction} {summary.total}</span>
))}
{Object.entries(message.reactions.multiple).map(([reaction, summary]) => (
<span key={`multiple-${reaction}`}>{reaction} {summary.total}</span>
))}
</div>
</div>
))}
</div>
);
};
const chatClient: ChatClient; // existing ChatClient instance
const App = () => {
return (
<ChatClientProvider client={chatClient}>
<ChatRoomProvider name="general-chat">
<MessageHandler />
</ChatRoomProvider>
</ChatClientProvider>
);
};
A hook that provides access to the Messages instance in the room.
If a listener is provided, it will subscribe to new messages in the room, and will also set the UseMessagesResponse.historyBeforeSubscribe.
Note: