tencent cloud

即时通信 IM

动态与公告
产品动态
公告
产品简介
产品概述
基本概念
应用场景
功能介绍
账号系统
用户资料与关系链
消息管理
群组相关
公众号系统
音视频通话 Call
使用限制
购买指南
计费概述
价格说明
购买指引
续费指引
停服说明
退费说明
开发指引
Demo 专区
开通服务
体验 Demo
快速跑通
下载中心
SDK & Demo 源码
更新日志
聊天互动(含 UI)
TUIKit 组件介绍
快速开始
全功能接入
单功能接入
AI 集成
构建基础界面
更多特性
定义外观
国际化界面语言
推送服务(Push)
服务概述
名词解释
开通服务
快速跑通
厂商通道
数据统计
排查工具
客户端 API
服务端 API
推送回调
高级功能
更新日志
错误码
常见问题
智能客服
功能概述
快速入门
集成指引
管理员操作手册
客服操作手册
更多实践
直播间搭建
AI 聊天机器人方案
超大娱乐协作社群
Discord 实现指南
游戏内集成 Chat 指南
类 WhatsApp Channel 搭建方案
发送红包
Chat 应对防火墙限制相关
无 UI 集成
快速开始
集成 SDK
初始化
登录登出
消息相关
会话相关
群组相关
社群话题
用户管理
离线推送
云端搜索
本地搜索
公众号
客户端 API
JavaScript
Android
iOS & macOS
Swift
Flutter
Electron
Unity
React Native
C 接口
C++
服务端 API
生成 UserSig
REST API
第三方回调
控制台指南
新版控制台介绍
创建并升级应用
基本配置
功能配置
账号管理
群组管理
公众号管理
回调配置
用量统计
资源包查看指南
实时监控
开发辅助工具
访问管理
高级功能
常见问题
uni-app 常见问题
购买相关问题
SDK 相关问题
账号鉴权相关问题
用户资料与关系链相关问题
消息相关问题
群组相关问题
直播群相关问题
昵称头像相关问题
协议与认证
服务等级协议
安全合规认证
IM 政策
隐私政策
数据隐私和安全协议
平滑迁移方案
平滑迁移完整版
平滑迁移简化版
错误码
联系我们

React

PDF
聚焦模式
字号
最后更新时间: 2026-03-03 14:18:06
TUIKit 是基于 IM SDK 的一款 UI 组件库,可通过 UI 组件快速实现聊天、会话、搜索、关系链、群组等功能。本文介绍如何快速集成 TUIKit 并实现核心功能。
您也可以使用 AI 集成,通过自然语言描述需求即可自动生成 TUIKit 集成代码。

前提条件

Node.js v18 版本及以上,建议使用当前的 LTS v22 版本
React^18.2 || React^19.0.0 版本

创建项目

创建一个新的名为 chat-app 的 React 项目,并按照脚手架提示完成项目的初始化。
npm create rsbuild@latest
# 初始化脚手架项目
cd chat-app
npm i
npm run dev

安装并引入组件

步骤1:安装依赖

通过 npm 方式下载 chat-uikit-react 并在项目中使用。
npm i @tencentcloud/chat-uikit-react

步骤2:引入组件

注意:
以下代码中未填入 SDKAppIDuserIDuserSig,需在 步骤3 中获取相关信息后进行替换。
为尊重表情设计版权,Chat Demo/TUIKit 工程中不包含大表情元素切图,正式上线商用前请您替换为自己设计或拥有版权的其他表情包。下图所示默认的小黄脸表情包版权归腾讯云所有,您可以通过升级至 Chat 专业版 Plus 和企业版 免费使用该表情包。



复制以下 App.tsx 代码并替换原有的 App.tsx 中的内容。
复制以下 App.css 代码并替换同级目录的 App.css 样式文件。
App.tsx
App.css
import {
UIKitProvider,
useLoginState,
LoginStatus,
ConversationList,
Chat,
ChatHeader,
MessageList,
MessageInput,
ContactList,
ContactInfo,
useUIKit,
useConversationListState,
} from "@tencentcloud/chat-uikit-react";
import { useEffect, useState } from "react";
import './App.css';

function App() {
// 语言支持 en-US(default) / zh-CN / ja-JP / ko-KR / zh-TW
// 主题支持 light(default) / dark
return (
<UIKitProvider theme={'light'} language={'en-US'}>
<ChatApp />
</UIKitProvider>
);
}

function ChatApp() {
const [activeTab, setActiveTab] = useState('chats');
const { language } = useUIKit();
const texts = language === 'zh-CN'
? { chats: '会话', contacts: '联系人', emptyTitle: '暂无会话', emptySub: '选择一个会话开始聊天', error: '请检查 SDKAppID, userID, userSig, 通过开发人员工具(F12)查看具体的错误信息', loading: '登录中...' }
: { chats: 'Chats', contacts: 'Contacts', emptyTitle: 'No conversation', emptySub: 'Select a conversation to start chatting', error: 'Please check the SDKAppID, userID, and userSig. View the specific error information through the developer tools (F12).', loading: 'Logging in...'};

const { status } = useLoginState({
SDKAppID: 0, // type: number
userID: '', // type: string
userSig: '', // type: string
})
const { setActiveConversation } = useConversationListState();

useEffect(() => {
async function init() {
// 你可以换成其他已创建的 userID
const userID = 'administrator';
const conversationID = `C2C${userID}`;
setActiveConversation(conversationID);
}

if (status === LoginStatus.SUCCESS) {
init();
}
}, [status]);

if (status === LoginStatus.ERROR) {
return (
<div className="loading-container">
<div className="loading-spinner"></div>
<div className="loading-text">{texts.error}</div>
</div>
)
}

if (status !== LoginStatus.SUCCESS) {
return (
<div className="loading-container">
<div className="loading-spinner"></div>
<div className="loading-text">{texts.loading}</div>
</div>
)
}

return (
<div className="chat-app">
<ul className="vertical-tabs">
<li
className={`tab-item ${activeTab === 'chats' ? 'active' : ''}`}
onClick={() => {setActiveTab('chats')}}
>
{texts.chats}
</li>
<li
className={`tab-item ${activeTab === 'contacts' ? 'active' : ''}`}
onClick={() => {setActiveTab('contacts')}}
>
{texts.contacts}
</li>
</ul>
{
activeTab === 'chats' && (
<>
<ConversationList style={{ flex: '0 0 300px'}}/>
<Chat
className="chat-box"
PlaceholderEmpty={
<div className="empty-chat">
<div className="empty-icon">💬</div>
<div className="empty-title">{texts.emptyTitle}</div>
<div className="empty-subtitle">{texts.emptySub}</div>
</div>
}
>
<ChatHeader />
<MessageList />
<MessageInput />
</Chat>
</>
)
}
{
activeTab === 'contacts' && (
<>
<ContactList style={{ flex: '0 0 300px'}}/>
<ContactInfo
style={{ flex: '1'}}
onSendMessage={() => {setActiveTab('chats')}}
onEnterGroup={() => {setActiveTab('chats')}}
/>
</>
)
}
</div>
);
}

export default App;
body {
margin: 0;
padding: 20px;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
box-sizing: border-box;
}

.chat-app {
height: calc(100vh - 40px);
max-width: 1400px;
margin: 0 auto;
display: flex;
flex-direction: row;
background: #ffffff;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3),
0 0 0 1px rgba(0, 0, 0, 0.1);
overflow: hidden;
backdrop-filter: blur(10px);
}

.vertical-tabs {
list-style: none;
margin: 0;
padding: 0;
width: 100px;
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
border-right: 1px solid rgba(0, 0, 0, 0.08);
}

.tab-item {
padding: 16px 20px;
cursor: pointer;
background: transparent;
color: #495057;
font-size: 14px;
text-align: center;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
}

.tab-item::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 0;
background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
border-radius: 0 3px 3px 0;
transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.tab-item:hover {
background: rgba(102, 126, 234, 0.08);
color: #667eea;
}

.tab-item.active {
background: linear-gradient(90deg, rgba(102, 126, 234, 0.15) 0%, rgba(102, 126, 234, 0.05) 100%);
color: #667eea;
}

.tab-item.active::before {
height: 60%;
}

.chat-box {
flex: 1;
border-left: 1px solid rgba(0, 0, 0, 0.08);
}

.empty-chat {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: #adb5bd;
gap: 12px;
text-align: center;
border-left: 1px solid rgba(0, 0, 0, 0.08);
}

.empty-icon {
font-size: 64px;
opacity: 0.3;
animation: float 3s ease-in-out infinite;
}

.empty-title {
font-size: 16px;
font-weight: 600;
color: #6c757d;
}

.empty-subtitle {
font-size: 14px;
color: #868e96;
}

@keyframes float {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(-10px);
}
}

.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
gap: 24px;
}

.loading-spinner {
width: 60px;
height: 60px;
border: 4px solid rgba(255, 255, 255, 0.2);
border-top-color: #ffffff;
border-radius: 50%;
animation: spin 1s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.loading-text {
color: #ffffff;
font-size: 18px;
font-weight: 500;
letter-spacing: 0.5px;
animation: pulse 2s ease-in-out infinite;
}

@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.6;
}
}


步骤3:获取 SDKAppID、userID 和 userSig

在之前复制的 App.tsx 代码中,登录鉴权信息是空缺的,您还需要在 useLoginState hook 中填写您的腾讯云应用的鉴权信息,如下所示:
参数
类型
说明
SDKAppID
Number
在创建的音频和视频应用程序中,作为唯一标识符为。可以在Tencent RTC 控制台中创建一个应用来获取SDKAppID。
userID
String
用户唯一标识符,可以在控制台中创建 2~3 个预设账号,用于互相发送消息,仅允许包含大小写字母(a-z, A-Z)、数字(0-9)、下划线和连字符。
secretKey
String
在创建的音频和视频应用程序中,secretKey作为密钥请妥善保存。可以在Tencent RTC 控制台中获取。
userSig
String
用于用户登录认证的安全保护签名,用于确认用户的身份并防止恶意攻击者窃取您的云服务使用权限。
可单击 即时通信 IM 控制台 > 开发工具 > UserSig 工具,填写创建的 userID,即可生成 userSig。
1. 登录 即时通信 IM 控制台,在应用管理页面,单击创建新应用。如果您已有应用,可省略创建应用过程。

2. 应用管理页面的 SDKAppID 列获取 SDKAppID 和密钥信息。

注意:
查看密钥信息需要验证身份。
密钥信息为敏感信息,为防止他人盗用,请妥善保管,谨防泄露。
3. 进入用户管理页面,创建 2~3 个测试账号,用于体验单聊能力和群聊能力。

4. userSig 信息,可单击 即时通信 IM 控制台 > 开发工具 > UserSig 工具,填写创建的 userID,即可生成 userSig。
用户签名说明:
开发环境:如果您在本地运行演示并进行调试开发,可以使用调试文件中的 genTestUserSig 函数(参见步骤 3.2)来生成 'userSig'。在此方法中,SDKSecretKey 易受反编译和逆向工程攻击。一旦您的密钥泄露,攻击者即可窃取您的腾讯云流量。
生产环境:如果您的项目即将上线,请使用服务端生成用户签名 的方法。

运行和测试

运行命令如下:
npm run dev
注意:
1. 请确保 步骤3 代码中 SDKAppIDuserIDuserSig 均已成功输入,如未替换将会导致项目表现异常。
2. userIDuserSig 为一一对应关系,具体参见 生成 UserSig
3. 如遇到项目启动失败,请检查 开发环境要求 是否满足。

发送您的第一条消息

体验单聊功能:搜索好友并发送您的第一条消息



体验群聊功能:创建群聊并发送一条消息



常见问题

什么是 UserSig?

UserSig 是用户登录 Chat 的密码,其本质是对 UserID 等信息加密后得到的密文。

如何生成 UserSig?

UserSig 签发方式是将 UserSig 的计算代码集成到您的服务端,并提供面向项目的接口,在需要 UserSig 时由您的项目向业务服务器发起请求获取动态 UserSig。更多详情请参见 服务端生成 UserSig
注意:
本文示例代码采用的获取 UserSig 的方案是在客户端代码中配置 SECRETKEY,该方法中 SECRETKEY 很容易被反编译逆向破解,一旦您的密钥泄露,攻击者就可以盗用您的腾讯云流量,因此该方法仅适合本地跑通功能调试。 正确的 UserSig 签发方式请参见上文。

是否支持 react 17 版本?

目前不支持 React v17.x,仅支持 React v18.2+ 以上的版本。

我能不能使用第三方组件库,例如 Ant-Design?

核心组件之间的粘连代码可以使用其他组件库,这一点在示例代码中也可以看到,例如您可以将 <ChatSetting /> 封装成全屏抽屉组件。但是核心组件内部已经存在的组件暂时不支持修改。
import { Drawer } from 'antd';

const [isChatSettingShow, setIsChatSettingShow] = useState(false);

function onChatSettingClose() {
setIsChatSettingShow(false);
}

<Drawer
title="设置"
onClose={onClose}
open={isChatSettingShow}
>
<ChatSetting />
</Drawer>

交流与反馈

加入 Telegram 技术交流群组WhatsApp 交流群,享有专业工程师的支持,解决您的难题。

相关文档

UIKit 相关:



帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈