@effectify/chat-react
@effectify/chat-react
Section titled “@effectify/chat-react”The @effectify/chat-react package provides real-time chat components and services for React applications. Built with Effect for robust state management and error handling, it offers a complete chat solution with WebSocket support, message persistence, and user management.
Installation
Section titled “Installation”npm install @effectify/chat-reactPeer Dependencies:
npm install @effectify/react-query @effectify/chat-domain reactBasic Usage
Section titled “Basic Usage”Simple Chat Component
Section titled “Simple Chat Component”import { ChatRoom } from "@effectify/chat-react/components/chat-room"
import { ChatProvider } from "@effectify/chat-react/components/chat-provider"
function App() {
return (
<ChatProvider
userId="user-123"
roomId="general"
websocketUrl="ws://localhost:3001"
>
<ChatRoom />
</ChatProvider>
)
}Custom Chat Interface
Section titled “Custom Chat Interface”import { ChatInput, ChatMessages, ChatUserList } from "@effectify/chat-react/components"
import { useChatRoom } from "@effectify/chat-react/hooks/use-chat-room"
function CustomChatRoom() {
const {
messages,
users,
sendMessage,
isConnected,
} = useChatRoom()
return (
<div className="flex h-screen">
<div className="flex-1 flex flex-col">
<div className="flex-1 overflow-y-auto">
<ChatMessages messages={messages} />
</div>
<ChatInput
onSendMessage={sendMessage}
disabled={!isConnected}
/>
</div>
<div className="w-64 border-l">
<ChatUserList users={users} />
</div>
</div>
)
}Components
Section titled “Components”ChatProvider
Section titled “ChatProvider”The root provider that manages chat state and WebSocket connections:
import { ChatProvider } from "@effectify/chat-react/components/chat-provider"
function App() {
return (
<ChatProvider
userId="current-user-id"
roomId="room-id"
websocketUrl="ws://localhost:3001"
options={{
reconnectAttempts: 5,
reconnectDelay: 1000,
messageHistory: 50,
}}
>
<YourChatComponents />
</ChatProvider>
)
}ChatRoom
Section titled “ChatRoom”A complete chat room component with messages, input, and user list:
import { ChatRoom } from "@effectify/chat-react/components/chat-room"
function MyChatApp() {
return (
<div className="h-screen">
<ChatRoom
className="h-full"
showUserList={true}
showTypingIndicator={true}
messageLimit={100}
/>
</div>
)
}ChatMessages
Section titled “ChatMessages”Displays a list of chat messages with proper formatting:
import { ChatMessages } from "@effectify/chat-react/components/chat-messages"
import { useChatRoom } from "@effectify/chat-react/hooks/use-chat-room"
function MessageArea() {
const { messages } = useChatRoom()
return (
<ChatMessages
messages={messages}
className="flex-1 overflow-y-auto p-4"
renderMessage={(message) => (
<div key={message.id} className="mb-2">
<strong>{message.user.name}:</strong> {message.content}
</div>
)}
/>
)
}ChatInput
Section titled “ChatInput”Input component for sending messages:
import { ChatInput } from "@effectify/chat-react/components/chat-input"
import { useChatRoom } from "@effectify/chat-react/hooks/use-chat-room"
function MessageInput() {
const { sendMessage, isConnected } = useChatRoom()
return (
<ChatInput
onSendMessage={sendMessage}
disabled={!isConnected}
placeholder="Type your message..."
maxLength={500}
showEmojiPicker={true}
onTyping={() => {
// Handle typing indicator
}}
/>
)
}ChatUserList
Section titled “ChatUserList”Displays online users in the chat room:
import { ChatUserList } from "@effectify/chat-react/components/chat-user-list"
import { useChatRoom } from "@effectify/chat-react/hooks/use-chat-room"
function UserSidebar() {
const { users } = useChatRoom()
return (
<div className="w-64 border-l bg-gray-50">
<h3 className="p-4 font-semibold">Online Users</h3>
<ChatUserList
users={users}
renderUser={(user) => (
<div key={user.id} className="flex items-center p-2">
<div className="w-2 h-2 bg-green-500 rounded-full mr-2" />
{user.name}
</div>
)}
/>
</div>
)
}useChatRoom
Section titled “useChatRoom”Main hook for accessing chat room state and actions:
import { useChatRoom } from "@effectify/chat-react/hooks/use-chat-room"
function ChatComponent() {
const {
// State
messages,
users,
currentUser,
isConnected,
isLoading,
error,
// Actions
sendMessage,
joinRoom,
leaveRoom,
// Typing indicators
typingUsers,
startTyping,
stopTyping,
} = useChatRoom()
const handleSendMessage = (content: string) => {
sendMessage({ content, type: "text" })
}
if (isLoading) return <div>Connecting to chat...</div>
if (error) return <div>Error: {error.message}</div>
return (
<div>
<div>Connected: {isConnected ? "Yes" : "No"}</div>
<div>Messages: {messages.length}</div>
<div>Users: {users.length}</div>
</div>
)
}useChatMessages
Section titled “useChatMessages”Hook for managing message-specific functionality:
import { useChatMessages } from "@effectify/chat-react/hooks/use-chat-messages"
function MessageManager() {
const {
messages,
sendMessage,
editMessage,
deleteMessage,
reactToMessage,
loadMoreMessages,
} = useChatMessages()
const handleEdit = (messageId: string, newContent: string) => {
editMessage(messageId, { content: newContent })
}
const handleReact = (messageId: string, emoji: string) => {
reactToMessage(messageId, emoji)
}
return (
<div>
{messages.map((message) => (
<div key={message.id}>
{message.content}
<button onClick={() => handleReact(message.id, "👍")}>
👍
</button>
</div>
))}
</div>
)
}Services
Section titled “Services”ChatService
Section titled “ChatService”Effect-based service for chat operations:
import { ChatService } from "@effectify/chat-react/services/chat-service"
import { Effect } from "effect"
// Send a message
const sendMessageEffect = ChatService.sendMessage({
roomId: "room-123",
content: "Hello, world!",
type: "text",
})
// Join a room
const joinRoomEffect = ChatService.joinRoom("room-123")
// Get message history
const getHistoryEffect = ChatService.getMessageHistory({
roomId: "room-123",
limit: 50,
before: new Date(),
})
// Usage in component
function ChatComponent() {
const sendMessage = (content: string) => {
Effect.runPromise(
sendMessageEffect.pipe(
Effect.catchAll((error) => {
console.error("Failed to send message:", error)
return Effect.succeed(null)
}),
),
)
}
return <div>{/* component JSX */}</div>
}Advanced Features
Section titled “Advanced Features”Message Reactions
Section titled “Message Reactions”import { MessageReactions } from "@effectify/chat-react/components/message-reactions"
function MessageWithReactions({ message }) {
const { reactToMessage } = useChatMessages()
return (
<div className="message">
<div>{message.content}</div>
<MessageReactions
reactions={message.reactions}
onReact={(emoji) => reactToMessage(message.id, emoji)}
/>
</div>
)
}File Uploads
Section titled “File Uploads”import { FileUpload } from "@effectify/chat-react/components/file-upload"
function ChatWithFiles() {
const { sendMessage } = useChatRoom()
const handleFileUpload = (file: File) => {
sendMessage({
type: "file",
content: file.name,
fileData: file,
})
}
return (
<div>
<FileUpload
onUpload={handleFileUpload}
acceptedTypes={["image/*", ".pdf", ".doc", ".docx"]}
maxSize={10 * 1024 * 1024} // 10MB
/>
</div>
)
}Typing Indicators
Section titled “Typing Indicators”import { TypingIndicator } from "@effectify/chat-react/components/typing-indicator"
function ChatWithTyping() {
const { typingUsers, startTyping, stopTyping } = useChatRoom()
const handleInputChange = (value: string) => {
if (value.length > 0) {
startTyping()
} else {
stopTyping()
}
}
return (
<div>
<div className="messages">
{/* messages */}
<TypingIndicator users={typingUsers} />
</div>
<input onChange={(e) => handleInputChange(e.target.value)} />
</div>
)
}Configuration
Section titled “Configuration”WebSocket Configuration
Section titled “WebSocket Configuration”const chatConfig = {
websocketUrl: 'ws://localhost:3001',
reconnectAttempts: 5,
reconnectDelay: 1000,
heartbeatInterval: 30000,
messageQueueSize: 100,
typingTimeout: 3000
}
<ChatProvider {...chatConfig}>
<ChatRoom />
</ChatProvider>Message Persistence
Section titled “Message Persistence”import { MessageStore } from '@effectify/chat-react/services/message-store'
// Configure local storage
const messageStore = MessageStore.localStorage({
maxMessages: 1000,
ttl: 7 * 24 * 60 * 60 * 1000 // 7 days
})
<ChatProvider messageStore={messageStore}>
<ChatRoom />
</ChatProvider>Error Handling
Section titled “Error Handling”import { ChatErrorBoundary } from "@effectify/chat-react/components/chat-error-boundary"
function App() {
return (
<ChatErrorBoundary
fallback={(error) => (
<div>
<h2>Chat Error</h2>
<p>{error.message}</p>
<button onClick={() => window.location.reload()}>
Reload
</button>
</div>
)}
>
<ChatProvider>
<ChatRoom />
</ChatProvider>
</ChatErrorBoundary>
)
}Examples
Section titled “Examples”Check out the complete chat implementation in:
API Reference
Section titled “API Reference”interface Message {
id: string
content: string
type: "text" | "file" | "system"
userId: string
user: User
timestamp: Date
reactions?: Reaction[]
edited?: boolean
}
interface User {
id: string
name: string
avatar?: string
status: "online" | "away" | "offline"
}
interface ChatRoom {
id: string
name: string
users: User[]
messages: Message[]
isPrivate: boolean
}