React UIKit chat components
React UIKit provides conversation, chat, friend and group UIs you can embed directly in your project. Here's how it relates to the Web SDK:
@deeprespond/im-web 协议、连接、消息和缓存
↓
@deeprespond/im-web-react React 订阅和生命周期
↓
@deeprespond/im-web-react-uikit 可组合的聊天界面
↓
业务项目 / UIKit 宿主示例The current version is 1.1.1, published to public npm. You can also build a local install package from the repository source, and the repository has a runnable example. React 18 and 19 are supported (React 18 has been tested in the browser). For Vue projects, use Vue UIKit.
Install from npm
Install matching versions of the core package, the bindings and UIKit in your React project:
pnpm add @deeprespond/im-web@1.1.1 @deeprespond/im-web-react@1.1.1 @deeprespond/im-web-react-uikit@1.1.1Pin a specific version. Your project provides React and React DOM. All components are exported from the package root, so there's no need to copy example source; import the styles separately.
Build from source and install offline
You only need to clone the repository to change component source or prepare an offline package. Node.js >= 20.19 (Node 22 recommended) and pnpm 9. From the repository root:
pnpm --dir sdk/web install
pnpm --dir sdk/web build
pnpm --dir sdk/web-react install
pnpm --dir sdk/web-react build
pnpm --dir sdk/web-react-uikit install
pnpm --dir sdk/web-react-uikit build
cd sdk/web-react-uikit
pnpm pack --pack-destination /tmp/react-uikit-packageWhen installing the local tgz in your project, still provide the core package and the bindings:
pnpm add @deeprespond/im-web@1.1.1 @deeprespond/im-web-react@1.1.1
pnpm add /tmp/react-uikit-package/deeprespond-im-web-react-uikit-1.1.1.tgzMinimal setup
Create the SDK client once where your app initializes, and sign in with a ticket issued by your backend:
import { createDRClient } from '@deeprespond/im-web';
export const client = createDRClient({
appKey: 'your-org#your-app',
apiUrl: 'https://your-im-api.example.com',
autoMarkRead: true,
});
// ticket 由自己的业务服务端签发,不在浏览器中保存 App Secret。
await client.auth.loginWithTicket({ ticket });Once signed in, embed it in a React component:
import { ChatApp, UIKitProvider } from '@deeprespond/im-web-react-uikit';
import '@deeprespond/im-web-react-uikit/styles.css';
import { client } from './im';
export function Messenger() {
return (
<section style={{ height: 640 }}>
<UIKitProvider client={client} theme="light">
<ChatApp title="业务消息" onLogout={() => client.auth.logout()} />
</UIKitProvider>
</section>
);
}UIKitProvideralready includesDRProvider, so you don't need to wrap it again.- When components unmount, they only clean up their own subscriptions, timers and media resources; they never sign out or destroy the client. Call
client.destroy()yourself when the app ends. - One page can have several
UIKitProviders, and their notifications, themes and component state are independent.
ChatApp shows a notice when nobody is signed in. Pass signedOut to customize it, or put a LoginPanel inside the Provider: by default it only offers ticket sign-in, and allowPassword and allowRegistration add password sign-in and registration. Whether users can sign in or register is still decided by the app's policies.
Composing components
| Component | API and purpose |
|---|---|
ChatApp | Full layout with conversations, friends, groups and chat; title, header, emptyState, signedOut, onLogout |
ChatWindow | A chat window on its own; conversationKey, optional conversation and onClose |
ConversationList | currentKey, onOpen(key, conversation); unread, pinned, muted and local drafts |
ContactList | onOpenPeer(username); friend requests, remarks, removal, blocklist |
GroupList | onOpenGroup(groupId), onOpenPeer(username); creating groups and managing members |
GroupMembers | groupId, onClose, onOpenPeer; group roles, inviting, and removal for the owner |
MessageBubble | message, optional conversation, renderBody, onResend; when used on its own it shows no conversation action menu |
MessageComposer | value, onChange, onSend; optional attachment, recording and quote callbacks and disabled. Your code does the sending |
ConnectionBanner | Connection status and recovery notices |
Avatar / Modal / Spinner | Avatar, a dialog with focus management, and a loading indicator |
useUIKit | The current instance's notifications, error formatting and feature settings |
ChatApp manages the selected conversation itself by default. To sync it with your router, pass conversationKey (a conversation key, or null for no selection) and handle onConversationChange. When a new one-to-one chat turns from a draft into a real conversation, the new key is reported the same way, so update your route.
Themes, messages and permissions
UIKitProvider accepts:
| Prop | Behavior |
|---|---|
theme | light / dark, applied only to this component container |
features | { images, files, voice }; set one to false to hide that input option |
readOnly / readOnlyReason | Removes text input, attachments and recording from chat and shows the reason. Doesn't restrict other writes such as friend actions |
renderMessage(message) | Returns custom message content; return undefined to use the built-in display |
formatError(error) | Custom error formatting; Chinese by default |
onError(error, action) | Receives operation errors for your logging. Don't log credentials such as tokens or passwords |
className / style | Adjusts the container and local CSS variables |
Styles apply only inside .dr-uikit, and the light and dark themes switch through the component's own data-theme; the page's html, body, theme settings and storage are never touched. You can override CSS variables such as --accent, --grad, --panel and --text. Give the container an explicit height; below 760px wide it shows a single column, with a back button in the chat window. Dialogs, image previews and notices appear inside the component container.
Hiding a button in the client only changes the UI; the server always has the final say on permissions. Reactions appear according to the app's policies, and owners and regular members see different management options. Images and files are downloaded through the SDK with authentication. Failed messages are kept with a resend option.
Run the example
# 在仓库根目录;先完成前面的核心、绑定、UIKit 构建
pnpm --dir sdk/web-react-uikit/demo install
pnpm --dir sdk/web-react-uikit/demo devIt runs at http://127.0.0.1:5198 by default. Set VITE_IM_APPKEY / VITE_IM_APIURL in the example's .env.local, or pass URL-encoded appKey / apiUrl parameters. The example allows password sign-in and registration for trying things out during development only; production apps should use their own authentication and tickets.
How it differs from the React project demo: the project demo shows how to write the UI with the hooks directly; the UIKit example assembles ready-made components, so you don't have to write a whole page yourself.
Coverage and limits
Included: one-to-one and group chat; text, image preview, files, voice recording and playback; send status and resend on failure, read receipts, quotes, recall, reactions, pinned messages, delete for me; friends and basic group management.
Not yet included: audio and video calls, chat rooms, standalone channels, complex forwarding, reports, and fuller group admin settings. When you need them, call the SDK directly with your own components. Unknown message types show a type notice, and you can customize them with renderMessage.
Tested environments: React 18 + Chromium against a real IM server, covering two users messaging each other and send failures, with screenshots checked at desktop and narrow widths. React 19, Next.js, Safari, Firefox, and microphone permissions and autoplay on mobile devices haven't been tested yet; verify in those environments before going live. Detailed results are in the repository's test report Agent测试/ReactUIKit/20261022/测试报告.md.
