Skip to main content
FieldValue
Package@cometchat/chat-uikit-react-native
Key componentsCometChatThreadHeader, CometChatMessageList, CometChatMessageComposer
InitCometChatUIKit.init(UIKitSettings) then CometChatUIKit.login("UID")
Entry pointPass parentMessageId prop to CometChatMessageList and CometChatMessageComposer
Sample appGitHub
RelatedMessage List · Thread Header · All Guides
Threaded messages let users create sub-conversations by replying to specific messages in group chats. This reduces clutter and keeps discussions focused. Before starting, complete the Getting Started guide.

Components

Component / ClassRole
CometChatThreadHeaderDisplays parent message context
CometChatMessageListShows messages filtered by parentMessageId
CometChatMessageComposerInput for composing threaded replies

Integration Steps

1. Thread View Screen

Create a dedicated screen for threaded messages that receives the parent message via navigation params.
import React, { useCallback } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { useRoute, useNavigation } from '@react-navigation/native';
import {
  CometChatThreadHeader,
  CometChatMessageList,
  CometChatMessageComposer,
  useTheme,
  useCometChatTranslation,
  Icon,
} from '@cometchat/chat-uikit-react-native';
import { CometChat } from '@cometchat/chat-sdk-react-native';

const ThreadView = () => {
  const route = useRoute();
  const navigation = useNavigation();
  const theme = useTheme();
  const { t } = useCometChatTranslation();
  
  const { message, user, group } = route.params || {};

  const handleBack = useCallback(() => {
    navigation.goBack();
  }, [navigation]);

  return (
    <View style={{ backgroundColor: theme.color.background1, flex: 1 }}>
      {/* Custom Header */}
      <View style={styles.headerStyle}>
        <TouchableOpacity onPress={handleBack}>
          {/* Back icon */}
        </TouchableOpacity>
        <View style={styles.textStyle}>
          <Text style={[theme.typography.heading1.bold, { color: theme.color.textPrimary }]}>
            {t('THREAD')}
          </Text>
          <Text
            style={[theme.typography.caption1.regular, { color: theme.color.textSecondary }]}
            numberOfLines={1}
          >
            {user ? user.getName() : group?.getName()}
          </Text>
        </View>
      </View>

      {/* Thread Header - shows parent message */}
      <CometChatThreadHeader parentMessage={message} />

      {/* Threaded Message List */}
      <View style={{ flex: 1 }}>
        <CometChatMessageList
          user={user}
          group={group}
          parentMessageId={message.getId().toString()}
        />
      </View>

      {/* Message Composer for Thread */}
      <CometChatMessageComposer
        user={user}
        group={group}
        parentMessageId={message.getId()}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  headerStyle: {
    paddingVertical: 10,
    paddingLeft: 10,
    flexDirection: 'row',
  },
  textStyle: {
    paddingLeft: 10,
    alignItems: 'flex-start',
  },
});

export default ThreadView;

2. Trigger Thread View from Messages

In your main messages screen, handle the onThreadRepliesClick callback to navigate to the thread view.
import React from 'react';
import { View } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import {
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from '@cometchat/chat-uikit-react-native';
import { CometChat } from '@cometchat/chat-sdk-react-native';

interface MessagesScreenProps {
  user?: CometChat.User;
  group?: CometChat.Group;
}

const MessagesScreen: React.FC<MessagesScreenProps> = ({ user, group }) => {
  const navigation = useNavigation();

  const handleThreadRepliesClick = (message: CometChat.BaseMessage) => {
    navigation.navigate('ThreadView', {
      message,
      user,
      group,
    });
  };

  return (
    <View style={{ flex: 1 }}>
      <CometChatMessageHeader user={user} group={group} />
      
      <CometChatMessageList
        user={user}
        group={group}
        onThreadRepliesClick={handleThreadRepliesClick}
      />
      
      <CometChatMessageComposer user={user} group={group} />
    </View>
  );
};

3. Navigation Setup

Configure React Navigation to include the ThreadView screen.
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MessagesScreen from './screens/MessagesScreen';
import ThreadView from './screens/ThreadView';

const Stack = createNativeStackNavigator();

const AppNavigator = () => {
  return (
    <Stack.Navigator screenOptions={{ headerShown: false }}>
      <Stack.Screen name="Messages" component={MessagesScreen} />
      <Stack.Screen name="ThreadView" component={ThreadView} />
    </Stack.Navigator>
  );
};

4. Navigate to Specific Message in Thread

Support navigating to a specific message within a thread using goToMessageId prop.
<CometChatMessageList
  user={user}
  group={group}
  parentMessageId={message.getId().toString()}
  goToMessageId={highlightMessageId} // Optional: scroll to specific message
/>

5. Handle Blocked Users in Threads

Show an unblock prompt when the user is blocked instead of the composer.
import React, { useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { CometChat } from '@cometchat/chat-sdk-react-native';
import {
  CometChatMessageComposer,
  CometChatUIEventHandler,
  CometChatUIEvents,
  useTheme,
  useCometChatTranslation,
} from '@cometchat/chat-uikit-react-native';

interface ThreadComposerProps {
  user?: CometChat.User;
  group?: CometChat.Group;
  parentMessageId: number;
}

const ThreadComposer: React.FC<ThreadComposerProps> = ({ user, group, parentMessageId }) => {
  const theme = useTheme();
  const { t } = useCometChatTranslation();
  const [localUser, setLocalUser] = useState(user);

  const unblock = async () => {
    if (!localUser) return;
    
    try {
      await CometChat.unblockUsers([localUser.getUid()]);
      const freshUser = await CometChat.getUser(localUser.getUid());
      setLocalUser(freshUser);
      
      CometChatUIEventHandler.emitUserEvent(
        CometChatUIEvents.ccUserUnBlocked,
        { user: freshUser }
      );
    } catch (error) {
      console.error('Error unblocking user:', error);
    }
  };

  if (localUser?.getBlockedByMe()) {
    return (
      <View style={{ alignItems: 'center', padding: 20, backgroundColor: theme.color.background3 }}>
        <Text style={{ color: theme.color.textSecondary, textAlign: 'center' }}>
          {t('BLOCKED_USER_DESC')}
        </Text>
        <TouchableOpacity onPress={unblock} style={{ marginTop: 10 }}>
          <Text style={{ color: theme.color.textPrimary }}>{t('UNBLOCK')}</Text>
        </TouchableOpacity>
      </View>
    );
  }

  return (
    <CometChatMessageComposer
      user={localUser}
      group={group}
      parentMessageId={parentMessageId}
    />
  );
};

Feature Matrix

FeatureComponent / Prop
Display parent messageCometChatThreadHeader with parentMessage prop
Show thread repliesCometChatMessageList with parentMessageId prop
Compose thread replyCometChatMessageComposer with parentMessageId prop
Navigate to messagegoToMessageId prop on CometChatMessageList
Thread triggeronThreadRepliesClick callback on CometChatMessageList

Next Steps