@vserifsaglam/chat-react-client
v1.0.5
Published
Frontend library to easliy connect to the chat
Readme
Chat React Client
A React library for integratin with the Chat Backend API
Features
- 🔒 Secure authentication with JWT tokens
- 🔄 Real-time chat functionality with WebSocket
- 📁 File uploads and attachments
- 📱 Responsive design
- 🧩 Modular architecture with React hooks
- 📝 TypeScript support
- 🔁 Automatic reconnection and fallback mechanisms
- 📋 Message queue for handling failed sends
- 📄 Pagination support for message history
- 🔔 Unread message indicators
- 🔄 Conversation and message management hooks for simplified integration
Installation
npm install --save chat-react-client
# or
yarn add chat-react-clientQuick Start
Wrap your application with the ChatClient component to provide authentication and API access:
import React from 'react';
import { ChatClient, ConnectionType } from 'chat-react-client';
const App = () => {
return (
<ChatClient
token="your_jwt_token"
baseUrl="https://api.example.com"
connectionOptions={{
connectionType: ConnectionType.WebSocket,
autoReconnect: true
}}
>
<YourChatComponent />
</ChatClient>
);
};
// Example with long polling only
const AppWithLongPolling = () => {
return (
<ChatClient
token="your_jwt_token"
baseUrl="https://api.example.com"
connectionOptions={{
connectionType: ConnectionType.LongPolling,
onlyLongpolling: true,
autoReconnect: true
}}
>
<YourChatComponent />
</ChatClient>
);
};
export default App;The connectionOptions prop allows you to configure the realtime connection:
connectionType: Select the connection type (WebSocket or LongPolling)autoReconnect: Automatically reconnect if the connection is lostonlyLongpolling: Force the connection to use long polling only (no WebSocket)
Hooks
useConversationManagement
A higher-level hook for managing conversations, including conversation selection and state management:
import React from 'react';
import { useConversationManagement } from 'chat-react-client';
const ConversationsManager = () => {
const {
conversations,
conversationsLoading,
selectedConversationId,
selectedConversation,
handleSelectConversation,
getConversations
} = useConversationManagement();
if (conversationsLoading) return <div>Loading conversations...</div>;
return (
<div className="chat-container">
<div className="conversations-list">
{conversations.map(conversation => (
<div
key={conversation.id}
className={`conversation ${selectedConversationId === conversation.id ? 'selected' : ''}`}
onClick={() => handleSelectConversation(conversation)}
>
<h3>{conversation.user.name}</h3>
<p>{conversation.lastMessage?.content}</p>
{conversation.unreadCount > 0 && (
<span className="unread-badge">{conversation.unreadCount}</span>
)}
</div>
))}
</div>
{selectedConversation && (
<div className="conversation-details">
<h2>Chat with {selectedConversation.user.name}</h2>
<MessagePanel conversationId={selectedConversationId} />
</div>
)}
</div>
);
};useMessageManagement
A higher-level hook for managing messages in a conversation, including pagination, file uploads, and real-time updates:
import React, { useState, useRef } from 'react';
import { useMessageManagement } from 'chat-react-client';
const MessagePanel = ({ conversationId, receiverId }) => {
const [messageText, setMessageText] = useState('');
const [file, setFile] = useState(null);
const messagesEndRef = useRef(null);
const {
messages,
messagesLoading,
fileLoading,
uploadProgress,
uploadFile,
handleSendMessage,
handleSendFileMessage,
loadMoreMessages,
hasMore
} = useMessageManagement(conversationId);
const handleSend = async () => {
if (!messageText.trim()) return;
const success = await handleSendMessage(messageText, receiverId);
if (success) {
setMessageText('');
}
};
const handleFileUpload = async (e) => {
const selectedFile = e.target.files[0];
if (!selectedFile) return;
setFile(selectedFile);
const fileId = await uploadFile(selectedFile);
if (fileId) {
await handleSendFileMessage(`Sent a file: ${selectedFile.name}`, fileId, receiverId);
setFile(null);
}
};
return (
<div className="message-panel">
{hasMore && (
<button
onClick={loadMoreMessages}
disabled={messagesLoading}
className="load-more-button"
>
{messagesLoading ? 'Loading...' : 'Load Previous Messages'}
</button>
)}
<div className="messages-container">
{messages.map(message => (
<div key={message.id} className={`message ${message.is_mine ? 'mine' : 'theirs'}`}>
<p>{message.content}</p>
{message.attachments?.length > 0 && (
<div className="attachments">
{message.attachments.map(attachment => (
<a key={attachment.id} href={attachment.url} target="_blank" rel="noopener noreferrer">
{attachment.filename}
</a>
))}
</div>
)}
<small>{new Date(message.timestamp).toLocaleString()}</small>
</div>
))}
<div ref={messagesEndRef} />
</div>
<div className="message-input">
{fileLoading && (
<div className="upload-progress">
<div className="progress-bar" style={{ width: `${uploadProgress}%` }}></div>
<span>{uploadProgress}%</span>
</div>
)}
<input
type="text"
value={messageText}
onChange={e => setMessageText(e.target.value)}
placeholder="Type a message..."
/>
<input type="file" onChange={handleFileUpload} />
<button onClick={handleSend} disabled={messagesLoading || fileLoading}>Send</button>
</div>
</div>
);
};useConversations
Access and manage conversations:
import React, { useEffect } from 'react';
import { useConversations } from 'chat-react-client';
const ConversationsList = () => {
const {
conversations,
loading,
error,
getConversations,
archiveConversation,
unarchiveConversation,
deleteConversation
} = useConversations();
useEffect(() => {
getConversations();
}, [getConversations]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
{conversations.map(conversation => (
<div key={conversation.id}>
<h3>{conversation.user.name}</h3>
<p>{conversation.lastMessage?.content}</p>
<button onClick={() => archiveConversation(conversation.id)}>
Archive
</button>
</div>
))}
</div>
);
};useMessages
Send and receive messages:
import React, { useState, useEffect } from 'react';
import { useMessages } from 'chat-react-client';
const ChatMessages = ({ conversationId }) => {
const [messageText, setMessageText] = useState('');
const {
messages,
loading,
sendMessage,
getMessages,
markConversationAsRead
} = useMessages(conversationId);
useEffect(() => {
if (conversationId) {
getMessages();
markConversationAsRead();
}
}, [conversationId, getMessages, markConversationAsRead]);
const handleSend = async () => {
if (!messageText.trim()) return;
await sendMessage({
receiver_client_id: 'recipient_id',
content: messageText
});
setMessageText('');
};
return (
<div>
<div className="messages-container">
{messages.map(message => (
<div key={message.id} className="message">
<p>{message.content}</p>
<small>{new Date(message.timestamp).toLocaleString()}</small>
</div>
))}
</div>
<div className="message-input">
<input
type="text"
value={messageText}
onChange={e => setMessageText(e.target.value)}
placeholder="Type a message..."
/>
<button onClick={handleSend} disabled={loading}>Send</button>
</div>
</div>
);
};useFiles
Upload files and attachments:
import React, { useState } from 'react';
import { useFiles, useMessages } from 'chat-react-client';
const FileUploader = ({ conversationId }) => {
const { uploadFile, uploadProgress, loading } = useFiles();
const { sendMessage } = useMessages(conversationId);
const [file, setFile] = useState(null);
const handleFileChange = (e) => {
setFile(e.target.files[0]);
};
const handleUpload = async () => {
if (!file) return;
const response = await uploadFile(file);
if (response) {
// Send a message with the file attachment
await sendMessage({
receiver_client_id: 'recipient_id',
content: 'I sent you a file',
attachments: [response.file_id]
});
}
};
return (
<div>
<input type="file" onChange={handleFileChange} />
{file && (
<>
<div className="progress-bar">
<div
className="progress"
style={{ width: `${uploadProgress}%` }}
></div>
</div>
<button onClick={handleUpload} disabled={loading}>
Upload and Send
</button>
</>
)}
</div>
);
};API Reference
ChatClient
The main component that provides authentication and API access.
Props:
token(string): JWT token for authenticationbaseUrl(string): Base URL of the Chat APIconnectionOptions(ConnectionOptions): Options for the realtime connectionchildren(ReactNode): Child components
ConnectionOptions
Options for configuring the realtime connection:
connectionType(ConnectionType): The type of connection to use (WebSocket or LongPolling)autoReconnect(boolean): Whether to automatically reconnect if the connection is lostreconnectAttempts(number): Maximum number of reconnection attemptsreconnectDelay(number): Delay between reconnection attempts in millisecondsonlyLongpolling(boolean): Force the connection to use long polling only (no WebSocket)
User
Interface representing a user in the chat system:
id(string): Unique identifier for the username(string): Display name of the useravatar(string): URL to the user's avatar imageis_admin(boolean): Whether the user is an adminattributes(Record<string, any>): Additional attributes for the userfile_storage_provider(string): The storage provider for the user's filesowner_client_id(string): The client ID of the user's owner
Conversation
Interface representing a conversation:
id(string): Unique identifier for the conversationstatus(string): Status of the conversation (e.g., "answered")user(User): The user participating in the conversationlastMessage(LastMessage): The last message in the conversationunreadCount(number): Number of unread messages in the conversation
ConversationDetails
Interface representing detailed information about a conversation:
conversation_uid(string): Unique identifier for the conversationuser_message_count(number): Number of messages sent by the useruser_attachment_count(number): Number of attachments sent by the useruser_attachments(Attachment[]): List of attachments sent by the userparticipants(User[]): List of participants in the conversation
useConversations
Hook for managing conversations.
Returns:
conversations(Conversation[]): List of conversationsloading(boolean): Loading stateerror(Error | null): Error stategetConversations(archived?: boolean, clientId?: string): Get conversationsdeleteConversation(conversationUid: string): Delete a conversationarchiveConversation(conversationUid: string): Archive a conversationunarchiveConversation(conversationUid: string): Unarchive a conversationgetConversationDetails(conversationUid: string): Get conversation detailssearchConversation(conversationUid: string, term: string): Search messages in a conversation
useMessages
Hook for managing messages.
Parameters:
conversationUid(string, optional): ID of the conversation
Returns:
messages(Message[]): List of messagespagination(MessagesPagination): Pagination informationloading(boolean): Loading stateerror(Error | null): Error stategetMessages(conversationId?: string, page?: number, pageSize?: number): Get messagesmarkMessageAsRead(messageId: number): Mark a message as readsendMessage(message: SendMessageRequest): Send a messagemarkConversationAsRead(conversationId?: string): Mark all messages in a conversation as readupdateMessage(messageId: number, update: UpdateMessageRequest): Update a messagedeleteMessage(messageId: number): Delete a message
useFiles
Hook for managing file uploads.
Returns:
loading(boolean): Loading stateerror(Error | null): Error stateuploadProgress(number): Upload progress (0-100)uploadFile(file: File): Upload a file
useConnection
Hook for managing the realtime connection.
Returns:
status(ConnectionStatus): Current connection statusisConnected(boolean): Whether the connection is activeisConnecting(boolean): Whether the connection is in progresshasError(boolean): Whether the connection has an errorconnect(): Connect to the serverdisconnect(): Disconnect from the serversendMessage(message: SendMessageRequest, maxAttempts?: number): Send a message with retry support
useRealtime
Hook for subscribing to realtime events.
Parameters:
eventType(EventType): The event type to subscribe to
Returns:
event(RealtimeEvent | null): The latest eventclearEvent(): Clear the current event
useMessageSentEvents
Hook for subscribing to message sent events.
Returns:
event(RealtimeEvent | null): The latest message sent eventclearEvent(): Clear the current event
useMessageEditedEvents
Hook for subscribing to message edited events.
Returns:
event(RealtimeEvent | null): The latest message edited eventclearEvent(): Clear the current event
useMessageDeletedEvents
Hook for subscribing to message deleted events.
Returns:
event(RealtimeEvent | null): The latest message deleted eventclearEvent(): Clear the current event
useConversationManagement
Hook for managing conversations with selection state.
Returns:
conversations(Conversation[]): List of conversationsconversationsLoading(boolean): Loading state for conversationsselectedConversationId(string): ID of the currently selected conversationselectedConversation(Conversation | undefined): The currently selected conversation objecthandleSelectConversation(conversation: Conversation): Function to select a conversationgetConversations(): Function to load conversations
useMessageManagement
Hook for managing messages in a conversation with pagination and file handling.
Parameters:
selectedConversationId(string): ID of the conversation to manage messages for
Returns:
messages(Message[]): List of messages in the conversationmessagesLoading(boolean): Loading state for messagesfileLoading(boolean): Loading state for file uploadsuploadProgress(number): Upload progress percentage (0-100)uploadFile(file: File): Function to upload a filehandleSendMessage(content: string, receiverId: string): Function to send a text messagehandleSendFileMessage(content: string, fileId: number, receiverId: string): Function to send a message with a file attachmentgetMessages(conversationId?: string, page?: number): Function to get messages for a conversationloadMoreMessages(): Function to load more messages (pagination)hasMore(boolean): Whether there are more messages to load
useAllMessageEvents
Hook for subscribing to all message events.
Returns:
messageSent(RealtimeEvent | null): The latest message sent eventmessageEdited(RealtimeEvent | null): The latest message edited eventmessageDeleted(RealtimeEvent | null): The latest message deleted eventclearEvents(): Clear all events
Realtime Examples
Connection Management
import React, { useEffect } from 'react';
import { useConnection, ConnectionStatus } from 'chat-react-client';
const ConnectionStatusComponent = () => {
const { status, isConnected, connect, disconnect } = useConnection();
useEffect(() => {
// Connect when the component mounts
connect();
// Disconnect when the component unmounts
return () => {
disconnect();
};
}, [connect, disconnect]);
return (
<div>
<div>Connection Status: {status}</div>
<button onClick={connect} disabled={isConnected}>
Connect
</button>
<button onClick={disconnect} disabled={!isConnected}>
Disconnect
</button>
</div>
);
};
### Event Listening
```tsx
import React, { useEffect, useState } from 'react';
import { useAllMessageEvents } from 'chat-react-client';
const MessageEventListener = () => {
const [messages, setMessages] = useState([]);
const {
messageSent,
messageEdited,
messageDeleted,
clearEvents
} = useAllMessageEvents();
// Handle new message
useEffect(() => {
if (messageSent) {
setMessages(prevMessages => [...prevMessages, messageSent.data]);
clearEvents();
}
}, [messageSent, clearEvents]);
// Handle edited message
useEffect(() => {
if (messageEdited) {
setMessages(prevMessages =>
prevMessages.map(msg =>
msg.id === messageEdited.data.msg_id
? { ...msg, content: messageEdited.data.new_content }
: msg
)
);
clearEvents();
}
}, [messageEdited, clearEvents]);
// Handle deleted message
useEffect(() => {
if (messageDeleted) {
setMessages(prevMessages =>
prevMessages.filter(msg => msg.id !== messageDeleted.data.msg_id)
);
clearEvents();
}
}, [messageDeleted, clearEvents]);
return (
<div>
<h3>Messages</h3>
<ul>
{messages.map(msg => (
<li key={msg.id}>{msg.content}</li>
))}
</ul>
</div>
);
};Complete Example
For a complete example of how to use the library, see the example directory.
License
MIT © vahit
