Field Value Package @cometchat/chat-uikit-reactCombined Component CometChatMessages — header, list, and composer in oneHeader Component CometChatMessageHeader — user/group info, call buttonsList Component CometChatMessageList — scrollable message feedComposer Component CometChatMessageComposer — text input with attachmentsPrimary Output onSendButtonClick: (message: CometChat.BaseMessage) => voidCSS Import @import url("@cometchat/chat-uikit-react/css-variables.css");CSS Root Classes .cometchat-message-header, .cometchat-message-list, .cometchat-message-composer
Overview
This guide shows you how to build messaging features in your React app. You’ll learn to display messages, send text and media, handle reactions, and implement threaded conversations.
Time estimate: 20 minutes
Difficulty: Beginner
Prerequisites
React.js Integration completed (CometChat initialized and user logged in)
Basic familiarity with React hooks (useState, useEffect)
Use Cases
The Messaging feature is ideal for:
One-on-one chat — Direct messaging between two users
Group chat — Multi-user conversations with shared message history
Support chat — Customer service messaging with threaded replies
Collaborative apps — Real-time messaging with media sharing and reactions
Required Components
Component Purpose CometChatMessageHeaderDisplays user/group avatar, name, status, and call buttons CometChatMessageListScrollable list of sent and received messages CometChatMessageComposerRich text input for composing and sending messages
Steps
Step 1: Basic Message View
Start with a complete message view for a user conversation:
import { useState , useEffect } from "react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import {
CometChatMessageHeader ,
CometChatMessageList ,
CometChatMessageComposer ,
} from "@cometchat/chat-uikit-react" ;
import "@cometchat/chat-uikit-react/css-variables.css" ;
function MessageView () {
const [ chatUser , setChatUser ] = useState < CometChat . User >();
useEffect (() => {
// Replace "uid" with the actual user ID
CometChat . getUser ( "uid" ). then (( user ) => setChatUser ( user ));
}, []);
if ( ! chatUser ) return < div > Loading... </ div > ;
return (
< div style = { { height: "100vh" , display: "flex" , flexDirection: "column" } } >
< CometChatMessageHeader user = { chatUser } />
< CometChatMessageList user = { chatUser } />
< CometChatMessageComposer user = { chatUser } />
</ div >
);
}
export default MessageView ;
This renders:
Header with user avatar, name, and online status
Scrollable message list with text, media, and reactions
Composer with text input, attachments, and emoji picker
Step 2: Group Message View
For group conversations, pass a group prop instead of user:
import { useState , useEffect } from "react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import {
CometChatMessageHeader ,
CometChatMessageList ,
CometChatMessageComposer ,
} from "@cometchat/chat-uikit-react" ;
import "@cometchat/chat-uikit-react/css-variables.css" ;
function GroupMessageView () {
const [ chatGroup , setChatGroup ] = useState < CometChat . Group >();
useEffect (() => {
// Replace "guid" with the actual group ID
CometChat . getGroup ( "guid" ). then (( group ) => setChatGroup ( group ));
}, []);
if ( ! chatGroup ) return < div > Loading... </ div > ;
return (
< div style = { { height: "100vh" , display: "flex" , flexDirection: "column" } } >
< CometChatMessageHeader group = { chatGroup } />
< CometChatMessageList group = { chatGroup } />
< CometChatMessageComposer group = { chatGroup } />
</ div >
);
}
export default GroupMessageView ;
Step 3: Sending Text Messages
The composer handles text message sending automatically. To customize the send behavior:
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import { CometChatMessageComposer } from "@cometchat/chat-uikit-react" ;
function CustomSendMessage ({ user } : { user : CometChat . User }) {
const handleSend = ( message : CometChat . BaseMessage ) => {
console . log ( "Message sent:" , message );
// Add custom logic here (analytics, validation, etc.)
};
return (
< CometChatMessageComposer
user = { user }
onSendButtonClick = { handleSend }
placeholderText = "Type your message..."
/>
);
}
Track Text Input
Monitor what the user types in real-time:
< CometChatMessageComposer
user = { user }
onTextChange = { ( text : string ) => {
console . log ( "User is typing:" , text );
} }
/>
The composer includes built-in attachment options for media:
import { CometChatMessageComposer } from "@cometchat/chat-uikit-react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
function MediaComposer ({ user } : { user : CometChat . User }) {
return (
< CometChatMessageComposer
user = { user }
// All attachment options enabled by default
// Hide specific options as needed:
hideImageAttachmentOption = { false }
hideVideoAttachmentOption = { false }
hideAudioAttachmentOption = { false }
hideFileAttachmentOption = { false }
/>
);
}
Custom Attachment Options
Add custom attachment actions:
import {
CometChatMessageComposer ,
CometChatMessageComposerAction ,
} from "@cometchat/chat-uikit-react" ;
function CustomAttachments ({ user } : { user : CometChat . User }) {
return (
< CometChatMessageComposer
user = { user }
attachmentOptions = { [
new CometChatMessageComposerAction ({
id: "location" ,
title: "Share Location" ,
iconURL: "location-icon-url" ,
onClick : () => console . log ( "Share location" ),
}),
new CometChatMessageComposerAction ({
id: "contact" ,
title: "Share Contact" ,
iconURL: "contact-icon-url" ,
onClick : () => console . log ( "Share contact" ),
}),
] }
/>
);
}
Step 5: Message Reactions
Reactions are enabled by default. Handle reaction events:
import { CometChatMessageList } from "@cometchat/chat-uikit-react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
function ReactionsHandler ({ user } : { user : CometChat . User }) {
return (
< CometChatMessageList
user = { user }
onReactionClick = { ( reaction : CometChat . ReactionCount , message : CometChat . BaseMessage ) => {
console . log ( "Reaction clicked:" , reaction , "on message:" , message . getId ());
} }
onReactionListItemClick = { ( reaction : CometChat . Reaction , message : CometChat . BaseMessage ) => {
console . log ( "Reaction detail:" , reaction , "on message:" , message . getId ());
} }
/>
);
}
Hide Reactions
To disable reactions entirely:
< CometChatMessageList
user = { user }
hideReactionOption = { true }
/>
Step 6: Threaded Messages
Enable threaded conversations by handling thread clicks:
import { useState } from "react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import {
CometChatMessageHeader ,
CometChatMessageList ,
CometChatMessageComposer ,
} from "@cometchat/chat-uikit-react" ;
function ThreadedMessages ({ user } : { user : CometChat . User }) {
const [ parentMessage , setParentMessage ] = useState < CometChat . BaseMessage >();
if ( parentMessage ) {
// Render threaded view
return (
< div style = { { height: "100vh" , display: "flex" , flexDirection: "column" } } >
< div style = { { padding: 16 , borderBottom: "1px solid #eee" } } >
< button onClick = { () => setParentMessage ( undefined ) } > ← Back to main </ button >
< span style = { { marginLeft: 16 } } > Thread </ span >
</ div >
< CometChatMessageList
user = { user }
parentMessageId = { parentMessage . getId () }
/>
< CometChatMessageComposer
user = { user }
parentMessageId = { parentMessage . getId () }
/>
</ div >
);
}
// Render main message view
return (
< div style = { { height: "100vh" , display: "flex" , flexDirection: "column" } } >
< CometChatMessageHeader user = { user } />
< CometChatMessageList
user = { user }
onThreadRepliesClick = { ( message : CometChat . BaseMessage ) => {
setParentMessage ( message );
} }
/>
< CometChatMessageComposer user = { user } />
</ div >
);
}
export default ThreadedMessages ;
Key points:
onThreadRepliesClick fires when a user clicks on thread reply count
Pass parentMessageId to both CometChatMessageList and CometChatMessageComposer for threaded view
Messages sent with parentMessageId become replies to that thread
Complete Example
Here’s a full implementation with user/group switching and threaded messages:
import { useState , useEffect } from "react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import {
CometChatMessageHeader ,
CometChatMessageList ,
CometChatMessageComposer ,
} from "@cometchat/chat-uikit-react" ;
import "@cometchat/chat-uikit-react/css-variables.css" ;
interface ChatMessagingProps {
userId ?: string ;
groupId ?: string ;
}
function ChatMessaging ({ userId , groupId } : ChatMessagingProps ) {
const [ chatUser , setChatUser ] = useState < CometChat . User >();
const [ chatGroup , setChatGroup ] = useState < CometChat . Group >();
const [ parentMessage , setParentMessage ] = useState < CometChat . BaseMessage >();
useEffect (() => {
if ( userId ) {
CometChat . getUser ( userId ). then (( user ) => {
setChatUser ( user );
setChatGroup ( undefined );
setParentMessage ( undefined );
});
} else if ( groupId ) {
CometChat . getGroup ( groupId ). then (( group ) => {
setChatGroup ( group );
setChatUser ( undefined );
setParentMessage ( undefined );
});
}
}, [ userId , groupId ]);
if ( ! chatUser && ! chatGroup ) {
return < div style = { { padding: 40 , textAlign: "center" } } > Select a user or group to start messaging </ div > ;
}
const handleThreadClick = ( message : CometChat . BaseMessage ) => {
setParentMessage ( message );
};
const handleBackToMain = () => {
setParentMessage ( undefined );
};
return (
< div style = { { height: "100vh" , display: "flex" , flexDirection: "column" } } >
{ parentMessage ? (
<>
< div style = { { padding: "12px 16px" , borderBottom: "1px solid #eee" , display: "flex" , alignItems: "center" , gap: 12 } } >
< button onClick = { handleBackToMain } style = { { background: "none" , border: "none" , cursor: "pointer" , fontSize: 16 } } >
← Back
</ button >
< span > Thread </ span >
</ div >
< CometChatMessageList
user = { chatUser }
group = { chatGroup }
parentMessageId = { parentMessage . getId () }
/>
< CometChatMessageComposer
user = { chatUser }
group = { chatGroup }
parentMessageId = { parentMessage . getId () }
/>
</>
) : (
<>
< CometChatMessageHeader
user = { chatUser }
group = { chatGroup }
showBackButton = { true }
/>
< CometChatMessageList
user = { chatUser }
group = { chatGroup }
onThreadRepliesClick = { handleThreadClick }
/>
< CometChatMessageComposer
user = { chatUser }
group = { chatGroup }
/>
</>
) }
</ div >
);
}
export default ChatMessaging ;
Custom Message Bubbles Replace the default message bubble rendering using templates: import {
CometChatMessageList ,
ChatConfigurator ,
CometChatActionsIcon ,
} from "@cometchat/chat-uikit-react" ;
function CustomBubbles ({ user } : { user : CometChat . User }) {
const getTemplates = () => {
const templates = ChatConfigurator . getDataSource (). getAllMessageTemplates ();
templates . map (( template ) => {
template . options = ( loggedInUser , message , group ) => {
const defaults = ChatConfigurator . getDataSource (). getMessageOptions (
loggedInUser , message , group
);
defaults . push (
new CometChatActionsIcon ({
id: "bookmark" ,
title: "Bookmark" ,
onClick : () => console . log ( "Bookmark message:" , message . getId ()),
})
);
return defaults ;
};
});
return templates ;
};
return < CometChatMessageList user = { user } templates = { getTemplates () } /> ;
}
Custom Composer Actions Replace the auxiliary button area: import { CometChatMessageComposer , CometChatButton } from "@cometchat/chat-uikit-react" ;
function CustomComposerActions ({ user } : { user : CometChat . User }) {
return (
< CometChatMessageComposer
user = { user }
auxiliaryButtonView = {
< CometChatButton
iconURL = "ai-icon-url"
onClick = { () => console . log ( "AI assist" ) }
/>
}
/>
);
}
Message Templates Customize how specific message types render. See Message Template for full documentation. Event Handling Listen to global message events: import { useEffect } from "react" ;
import { CometChatMessageEvents } from "@cometchat/chat-uikit-react" ;
function useMessageEvents () {
useEffect (() => {
const sentSub = CometChatMessageEvents . ccMessageSent . subscribe (
( data ) => console . log ( "Message sent:" , data )
);
const editedSub = CometChatMessageEvents . ccMessageEdited . subscribe (
( data ) => console . log ( "Message edited:" , data )
);
const deletedSub = CometChatMessageEvents . ccMessageDeleted . subscribe (
( msg ) => console . log ( "Message deleted:" , msg )
);
return () => {
sentSub ?. unsubscribe ();
editedSub ?. unsubscribe ();
deletedSub ?. unsubscribe ();
};
}, []);
}
Event Fires When ccMessageSentA message is sent ccMessageEditedA message is edited ccMessageDeletedA message is deleted ccMessageReadA message is read ccReplyToMessageUser replies to a message
Key CSS Selectors Target Selector Message header root .cometchat-message-headerMessage list root .cometchat-message-listMessage composer root .cometchat-message-composerOutgoing bubble .cometchat-message-bubble-outgoingIncoming bubble .cometchat-message-bubble-incomingSend button .cometchat-message-composer__send-buttonThread replies .cometchat-message-bubble__thread-view-replies
Example: Custom Bubble Colors .cometchat-message-bubble-outgoing {
background : #6852d6 ;
}
.cometchat-message-bubble-incoming {
background : #f5f5f5 ;
}
.cometchat-message-composer__send-button-active {
background : #6852d6 ;
}
Common Issues
Components must not render until CometChat is initialized and the user is logged in. Gate rendering with state checks.
Issue Solution Messages not loading Ensure user or group prop is passed correctly; check console for errors Send button not working Verify onSendButtonClick callback doesn’t prevent default behavior Reactions not showing Check hideReactionOption is not set to true Thread view not opening Ensure onThreadRepliesClick handler updates state correctly Media attachments failing Verify file size limits and supported formats Typing indicator not showing Check disableTypingEvents is not set to true on composer
For more help, see the Troubleshooting Guide or contact CometChat Support .
Next Steps