npm create rsbuild@latest# 初始化脚手架项目cd chat-appnpm inpm run dev
npm i @tencentcloud/chat-uikit-react
SDKAppID、userID 和 userSig,需在 步骤3 中获取相关信息后进行替换。
App.tsx 代码并替换原有的 App.tsx 中的内容。App.css 代码并替换同级目录的 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) / darkreturn (<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: numberuserID: '', // type: stringuserSig: '', // type: string})const { setActiveConversation } = useConversationListState();useEffect(() => {async function init() {// 你可以换成其他已创建的 userIDconst 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"><liclassName={`tab-item ${activeTab === 'chats' ? 'active' : ''}`}onClick={() => {setActiveTab('chats')}}>{texts.chats}</li><liclassName={`tab-item ${activeTab === 'contacts' ? 'active' : ''}`}onClick={() => {setActiveTab('contacts')}}>{texts.contacts}</li></ul>{activeTab === 'chats' && (<><ConversationList style={{ flex: '0 0 300px'}}/><ChatclassName="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'}}/><ContactInfostyle={{ 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;}}
App.tsx 代码中,登录鉴权信息是空缺的,您还需要在 useLoginState hook 中填写您的腾讯云应用的鉴权信息,如下所示:参数 | 类型 | 说明 |
SDKAppID | Number | |
userID | String | |
secretKey | String | |
userSig | String | 用于用户登录认证的安全保护签名,用于确认用户的身份并防止恶意攻击者窃取您的云服务使用权限。 |



genTestUserSig 函数(参见步骤 3.2)来生成 'userSig'。在此方法中,SDKSecretKey 易受反编译和逆向工程攻击。一旦您的密钥泄露,攻击者即可窃取您的腾讯云流量。npm run dev
SDKAppID、userID 和 userSig 均已成功输入,如未替换将会导致项目表现异常。userID 和 userSig 为一一对应关系,具体参见 生成 UserSig。

文档反馈