本技能基于 @cometchat/chat-uikit-react-native@5 与目录 rn-v5.json,说明 CometChat React Native UI Kit v5 的各个界面在真实 App 中应放置于何处。它假定读者已掌握配套技能 cometchat-react-native-core(安装、Provider 链、init→login→render),因此不重复这些内容。
适用场景
当需求为“添加一个聊天标签页”“把聊天放在独立屏幕上”“把聊天嵌入现有 App”“构建完整聊天 App”“如何从列表导航到会话”时使用本技能。
前置条件与安装
导航库不随包提供。文档给出的安装命令为:
npm install @react-navigation/native @react-navigation/native-stack @react-navigation/bottom-tabs npm install react-native-screens react-native-safe-area-context
需将这些依赖对齐到自己的 React Native 版本,不要直接取最新版。UI Kit 将其 peer 依赖声明为 "*",因此不会对版本形成约束。react-native-screens 4.x / safe-area-context 5.x 使用 Fabric codegen,RN 0.77 的 @react-native/codegen 无法解析,Metro 会报出 Unknown prop type for "moduleId" / "onFinishTransitioning" 这类指向原生 codegen 文件、而非 CometChat 的错误。可运行 npx react-native doctor,或为你的 RN 匹配一组已知可用版本(在 0.77 上:gesture-handler@2.32.0 + screens@4.4.0 + safe-area-context@4.14.0)。
支配所有布局的规则:每个路由一个屏幕
这是与 Web UI Kit 最大的区别。React 端会把列表和消息面板并排摆放,并用状态切换侧面板;在手机上这是错误的做法:每个界面都是栈导航器上的独立屏幕;导航使用 navigation.navigate(...),而非条件渲染;返回由硬件/手势返回按钮完成,由操作系统提供,不要手写;没有侧面板,搜索、话题和详情都是 push 出来的屏幕。条件渲染({selected ? <Chat/> : <List/>})出现在最简单的文档示例中,对单屏演示尚可,但会破坏 Android 返回按钮并丢失导航状态。任何超出演示的场景都应使用导航器。
Provider 链与导航器的顺序
Provider 包裹导航器,而不是相反。GestureHandlerRootView 保持最外层。示例代码:
import { GestureHandlerRootView } from "react-native-gesture-handler"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { NavigationContainer } from "@react-navigation/native"; import { CometChatI18nProvider, CometChatThemeProvider, } from "@cometchat/chat-uikit-react-native";
export const Root = ({ children }: { children: React.ReactNode }) => ( <GestureHandlerRootView style={{ flex: 1 }}> <SafeAreaProvider> <CometChatI18nProvider> <CometChatThemeProvider> <NavigationContainer>{children}</NavigationContainer> </CometChatThemeProvider> </CometChatI18nProvider> </SafeAreaProvider> </GestureHandlerRootView> );
若把 NavigationContainer 放在 Provider 之外,屏幕挂载时将没有主题,套件会回退到默认值。
放置方式 1 — 聊天独占屏幕(默认)
两条路由:列表和消息面板。这是无特定范围的“添加聊天”应产生的结果。示例代码:
import { createNativeStackNavigator } from "@react-navigation/native-stack"; import { CometChatConversations } from "@cometchat/chat-uikit-react-native";
const Stack = createNativeStackNavigator();
const ConversationsScreen = () => <CometChatConversations />;
const MessagesScreen = () => null; // header + list + composer — see core
export const ChatStack = () => ( <Stack.Navigator> <Stack.Screen name="Conversations" component={ConversationsScreen} /> <Stack.Screen name="Messages" component={MessagesScreen} options={{ headerShown: false }} /> </Stack.Navigator> );
消息屏幕设置 headerShown: false,因为 CometChatMessageHeader 本身就是头部;保留原生头部会出现两个叠加的头部。列表屏幕在 onItemPress 时导航;消息屏幕从路由参数读取 user/group,设置 showBackButton(在 RN 上默认为 false),并将 onBack 接到 navigation.goBack()。
放置方式 2 — 在现有 App 中增加聊天标签页
聊天成为与自有屏幕并列的一个标签页。底部标签导航器承载各标签;其上方放一个栈,使打开会话时消息屏幕覆盖标签栏。示例代码:
<Stack.Navigator> <Stack.Screen name="Tabs" component={TabNavigator} options={{ headerShown: false }} /> <Stack.Screen name="Messages" component={MessagesScreen} options={{ headerShown: false }} /> </Stack.Navigator>
若把 Messages 放在标签导航器内部,标签栏会一直显示在输入框上方,即典型的“键盘与标签栏打架”问题。
放置方式 3 — 扩展为完整 App
按需求逐步为其他目录添加标签页,每个都是独立屏幕:CometChatConversations(Chats)、CometChatUsers(Users)、CometChatGroups(Groups)、CometChatCallLogs(Calls)。要 push,不要用面板:话题回复 push 一个带 CometChatThreadHeader 的屏幕;搜索 push 一个带 CometChatSearch 的屏幕并接好 onBack;群成员 push 一个带 CometChatGroupMembers 的屏幕;用户/群详情需要自行构建,套件 v5 不提供详情组件(SDK 回退方案见 core/references/docs-map.md)。CometChatIncomingCall 是例外:在导航器上方挂载一次,使来电可在任意屏幕到达。
放置方式 4 — 嵌入现有屏幕
聊天作为屏幕的一部分而非全部。容器仍须为 flex: 1 且 minHeight: 0;固定高度在键盘弹出时会出问题。
尺寸与键盘
套件组件的每个祖先都应为 flex: 1。可滚动列还需要 minHeight: 0。请在键盘打开的状态下验证,输入框必须保持可见,模拟器可能给出误导。
常见陷阱
两个头部——任何使用 CometChatMessageHeader 的屏幕都要设 headerShown: false。消息屏幕放在标签导航器内——标签栏会遮挡输入框。从 Web 移植侧面板——应改为 push 屏幕。NavigationContainer 放在 Provider 之外——屏幕挂载时无主题。手写返回按钮——使用导航器自带的,并将 onBack 接到 navigation.goBack()。CometChatIncomingCall 放在单个屏幕内——来电只会在该屏幕到达。
验证
每个生成的组件都出现在 catalogs/rn-v5.json 中。npm run verify:fences:rn-v5 通过。在设备上:硬件返回可从消息屏幕返回;打开搜索/话题后按返回能干净返回;输入框在键盘弹出后仍可用;在任意标签页都能收到来电。