React

最近更新时间:2026-07-01 16:34:30

我的收藏

组件概述

Search 是一个功能完整的搜索解决方案,包含了搜索框、搜索结果展示、高级搜索等功能的完整组件集合。适用于即时通信、在线会议、在线教育等场景的用户、群组、消息搜索。
说明:
此功能属于增值服务,需要您购买云端搜索插件,请点击 购买


组件架构

Search (主组件)
├── SearchBar # 搜索框组件
├── SearchResults # 搜索结果组件
├── SearchAdvanced # 高级搜索组件
└── SearchResultsItem # 搜索结果项组件
├── User # 用户结果项
├── Group # 群组结果项
├── Message # 消息结果项
└── Conversation # 会话结果项

搜索模式

迷你模式
标准模式
嵌入式模式
适用于侧边栏或小容器
显示有限结果数量
支持展开查看更多
适用于全屏搜索界面
完整功能展示
支持高级搜索
适用于聊天界面
专注消息搜索
优化的布局




Props

属性名
类型
默认值
说明
variant
VariantType
VariantType.MINI
搜索模式:mini(迷你)、standard(标准)、embedded(嵌入式)。
SearchBar
React.ComponentType<SearchBarProps>
DefaultSearchBar
自定义搜索框组件。
SearchResults
React.ComponentType<SearchResultsProps>
DefaultSearchResults
自定义搜索结果组件。
SearchAdvanced
React.ComponentType<SearchAdvancedProps>
DefaultSearchAdvanced
自定义高级搜索组件。
SearchResultsPresearch
React.ComponentType
-
搜索前占位符组件。
SearchResultsLoading
React.ComponentType
-
加载中占位符组件。
SearchResultsEmpty
React.ComponentType
-
空结果占位符组件。
SearchResultItem
React.ComponentType<ResultItemProps>
-
自定义搜索结果项组件。
debounceTime
number
300
搜索防抖时间(毫秒)。
autoFocus
boolean
false
是否自动聚焦搜索框。
className
string
-
自定义样式类名。
style
React.CSSProperties
-
自定义样式。
onKeywordChange
(keyword: string) => void
-
搜索关键词变化回调。
onSearchComplete
(results: Map<SearchType, SearchResult>) => void
-
搜索完成回调。
onResultItemClick
(data: SearchResultItem, type: SearchType) => void
-
搜索结果点击回调。
onError
(error: Error) => void
-
搜索错误回调。

基础使用

import { Search, VariantType } from '@tencentcloud/chat-uikit-react';

function App() {
return (
<Search
variant={VariantType.STANDARD}
onResultItemClick={(data, type) => {
console.log('搜索结果点击:', data, type);
}}
/>
);
}

自定义能力

Search 为用户自定义提供了丰富且多维度的 Props 接口,允许用户自定义功能、UI、模块等。
Search 组件提供了多个可替换的子组件,允许用户自定义 SearchBar, SearchResults, SearchAdvanced, SearchResultItem, SearchResultsPresearch, SearchResultsLoading, SearchResultsEmpty, 等。同时,用户还可以利用默认子组件进行二次开发定制。
自定义 SearchBar
自定义 SearchResults
自定义 SearchAdvanced
自定义 SearchResultItem
自定义占位组件
Props
属性名
类型
默认值
说明
data
SearchResultItem
-
搜索结果数据。
type
SearchType
-
搜索结果类型。
keyword
string
-
搜索关键词。
onClick
(data: SearchResultItem, type: SearchType) => void
-
点击回调。
className
string
-
自定义样式类名。
示例
const CustomSearchBar = ({ value, onChange, onClear, placeholder }) => (
<div className="custom-search-bar">
<input
type="text"
value={value}
onChange={onChange}
placeholder={placeholder}
/>
{value && <button onClick={onClear}>清除</button>}
</div>
);

<Search SearchBar={CustomSearchBar} />
Props
属性名
类型
默认值
说明
results
Map<SearchType, SearchResult>
-
搜索结果数据
isLoading
boolean
-
是否正在加载
error
Error | null
-
错误信息
keyword
string
-
搜索关键词
typeLabels
Record<SearchType, string>
-
搜索类型标签
onLoadMore
(type: SearchType) => void
-
加载更多回调
onResultItemClick
(data: SearchResultItem, type: SearchType) => void
-
结果项点击回调
SearchResultsLoading
React.ComponentType
Loading
自定义加载组件
SearchResultsPresearch
React.ComponentType
-
搜索前占位符组件
SearchResultsEmpty
React.ComponentType
EmptyResult
空结果占位符组件
SearchResultItem
React.ComponentType<ResultItemProps>
DefaultSearchResultsItem
自定义结果项组件
variant
VariantType
VariantType.STANDARD
显示模式
searchType
SearchType | 'all'
'all'
当前搜索类型
示例
const CustomSearchResults = ({ results, keyword, onResultItemClick }) => (
<div className="custom-results">
{Array.from(results.entries()).map(([type, result]) => (
<div key={type}>
<h3>{type}</h3>
{result.resultList.map((item, index) => (
<div key={index} onClick={() => onResultItemClick(item, type)}>
{/* 自定义结果项 */}
</div>
))}
</div>
))}
</div>
);

<Search SearchResults={CustomSearchResults} />
Props
属性名
类型
默认值
说明
variant
VariantType
-
显示模式
searchType
SearchTabType
-
当前搜索类型
advancedParams
Map<SearchType, SearchParamsMap[SearchType]>
-
高级搜索参数
onAdvancedParamsChange
(type: SearchType, params: SearchParamsMap[SearchType]) => void
-
参数变化回调
示例
const CustomSearchAdvanced = ({ variant, searchType, advancedParams, onAdvancedParamsChange }) => (
<div className="custom-advanced">
{/* 自定义高级搜索功能 */}
</div>
);

<Search SearchAdvanced={CustomSearchAdvanced} />
Props
属性名
类型
默认值
说明
data
SearchResultItem
-
搜索结果数据
type
SearchType
-
搜索结果类型
keyword
string
-
搜索关键词
onClick
(data: SearchResultItem, type: SearchType) => void
-
点击回调
className
string
-
自定义样式类名
示例
const CustomSearchItem = ({ data, type, keyword, onClick }) => (
<div className="custom-item">
{type === SearchType.MESSAGE && (
<Conversation
data={data}
keyword={keyword}
onClick={onClick}
/>
)}
{type === SearchType.USER && (
<User
data={data}
keyword={keyword}
onClick={onClick}
/>
)}
{type === SearchType.GROUP && (
<Group
data={data}
keyword={keyword}
onClick={onClick}
/>
)}
{type === SearchType.CHAT_MESSAGE && (
<Message
data={data}
keyword={keyword}
onClick={onClick}
/>
)}
</div>
);

<Search SearchResultItem={CustomSearchItem} />
Props
属性名
类型
默认值
说明
SearchResultsPresearch
React.ComponentType
-
搜索前占位符组件
SearchResultsLoading
React.ComponentType
-
加载中占位符组件
SearchResultsEmpty
React.ComponentType
-
空结果占位符组件
示例
<Search
SearchResultsPresearch={() => <div>输入关键词开始搜索</div>}
SearchResultsLoading={() => <div>搜索中...</div>}
SearchResultsEmpty={() => <div>未找到相关结果</div>}
/>

SearchStore

SearchStore 提供了基于云端搜索的搜索能力。如果自定义组件能力不能支持您的业务,可以使用 SearchStore 实现您的需求。

属性

属性名
类型
说明
userList
UserProfile[]
用户搜索结果列表。
userTotalCount
number
用户搜索结果总数。
hasMoreUsers
boolean
用户搜索结果是否还有下一页。
groupList
GroupSearchInfo[]
群组搜索结果列表。
groupTotalCount
number
群组搜索结果总数。
hasMoreGroups
boolean
群组搜索结果是否还有下一页。
groupMemberList
Record<string, GroupMember[]>
群成员搜索结果,按 groupID 分组。
groupMemberTotalCount
number
群成员搜索结果总数。
hasMoreGroupMembers
boolean
群成员搜索结果是否还有下一页。
messageResults
MessageSearchResultItem[]
消息搜索结果列表。每项按会话聚合,包含会话 ID、会话展示信息、命中消息数量和消息列表。
messageResultTotalCount
number
消息搜索结果总数。
hasMoreMessageResults
boolean
消息搜索结果是否还有下一页。

方法

方法名
类型
说明
search
(keywordList: string[], option?: SearchOption) => Promise<void>
发起搜索。默认会同时搜索用户、群组、群成员和消息;可通过 option.searchScope 限制搜索范围。调用时会重置当前结果和分页游标。
searchMore
(searchType: SearchType) => Promise<void>
加载指定搜索类型的下一页结果。searchType 可为 User、Group、GroupMember、Message。
destroy
() => void
销毁当前 SearchStore 实例,清理订阅和状态。通常由 React/Vue3 封装层自动管理。
SearchOption
字段名
类型
说明
keywordListMatchMode
KeywordListMatchMode
多关键词匹配模式:Or 或 And。默认 Or。
searchScope
SearchType[]
搜索范围。默认包含用户、群组、群成员、消息四类。
pageSize
number
每页数量,默认 20。
userFilter
UserSearchFilter
用户搜索过滤条件。
messageFilter
MessageSearchFilter
消息搜索过滤条件。
groupMemberFilter
GroupMemberSearchFilter
群成员搜索过滤条件。

使用示例

index.tsx
index.css
import { useState } from 'react';
import {
SearchType,
SearchStore,
} from '@tencentcloud/chat-uikit-react';
import './styles.css';

function SearchStoreBasicDemo() {
const {
hasMoreUsers,
search,
searchMore,
userList,
userTotalCount,
} = SearchStore.create();

const [keyword, setKeyword] = useState('');
const [hasSearched, setHasSearched] = useState(false);
const [isLoading, setIsLoading] = useState(false);

const handleSearch = async () => {
const nextKeyword = keyword.trim();
if (!nextKeyword) {
return;
}

setIsLoading(true);
setHasSearched(true);
try {
await search([nextKeyword], {
pageSize: 20,
searchScope: [SearchType.User],
});
} finally {
setIsLoading(false);
}
};

const handleLoadMore = async () => {
setIsLoading(true);
try {
await searchMore(SearchType.User);
} finally {
setIsLoading(false);
}
};

return (
<div className="search-store-basic-demo">
<div className="search-store-basic-demo__header">
<h2>Search Store Basic</h2>
<p>Very simple user search powered by SearchStore.</p>
</div>

<div className="search-store-basic-demo__toolbar">
<input
onChange={event => setKeyword(event.target.value)}
onKeyDown={event => {
if (event.key === 'Enter') {
handleSearch();
}
}}
placeholder="Enter user keyword"
value={keyword}
/>
<button disabled={isLoading || !keyword.trim()} onClick={handleSearch} type="button">
{isLoading ? 'Searching...' : 'Search'}
</button>
</div>

<div className="search-store-basic-demo__panel">
<h3>Users ({userTotalCount})</h3>
{userList.length > 0 ? (
<ul className="search-store-basic-demo__list">
{userList.map(user => (
<li className="search-store-basic-demo__item" key={user.userID}>
<span className="search-store-basic-demo__avatar">
{(user.nickname || user.userID).slice(0, 1).toUpperCase()}
</span>
<span>
<strong>{user.nickname || user.userID}</strong>
<small>{user.userID}</small>
</span>
</li>
))}
</ul>
) : (
<div className="search-store-basic-demo__empty">
{hasSearched ? 'No users found.' : 'Enter a keyword and search.'}
</div>
)}
</div>

{hasMoreUsers && (
<button
className="search-store-basic-demo__more"
disabled={isLoading}
onClick={handleLoadMore}
type="button"
>
Load More
</button>
)}
</div>
);
}
.search-store-basic-demo {
display: flex;
height: 100%;
flex-direction: column;
gap: 16px;
padding: 24px;
overflow: hidden;
}

.search-store-basic-demo__header h2 {
margin: 0 0 8px;
color: #111827;
font-size: 22px;
}

.search-store-basic-demo__header p {
margin: 0;
color: #6b7280;
font-size: 14px;
}

.search-store-basic-demo__toolbar {
display: flex;
gap: 8px;
}

.search-store-basic-demo__toolbar input {
width: 260px;
padding: 8px 10px;
border: 1px solid #d7dce5;
border-radius: 8px;
}

.search-store-basic-demo__toolbar button,
.search-store-basic-demo__more {
padding: 8px 12px;
border: 1px solid #667eea;
border-radius: 8px;
background: #667eea;
color: #fff;
cursor: pointer;
}

.search-store-basic-demo__toolbar button:disabled,
.search-store-basic-demo__more:disabled {
opacity: 0.6;
cursor: not-allowed;
}

.search-store-basic-demo__panel {
display: flex;
width: min(560px, 100%);
min-height: 0;
flex: 1;
flex-direction: column;
overflow: hidden;
border: 1px solid #edf0f5;
border-radius: 12px;
background: #fff;
}

.search-store-basic-demo__panel h3 {
margin: 0;
padding: 14px 16px;
border-bottom: 1px solid #edf0f5;
color: #111827;
font-size: 15px;
}

.search-store-basic-demo__list {
display: flex;
flex-direction: column;
gap: 8px;
margin: 0;
padding: 12px;
overflow: auto;
list-style: none;
}

.search-store-basic-demo__item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border-radius: 10px;
background: #f9fafb;
}

.search-store-basic-demo__avatar {
display: inline-flex;
width: 32px;
height: 32px;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #eef2ff;
color: #4f46e5;
font-size: 13px;
font-weight: 700;
}

.search-store-basic-demo__item strong,
.search-store-basic-demo__item small {
display: block;
}

.search-store-basic-demo__item strong {
color: #111827;
font-size: 14px;
}

.search-store-basic-demo__item small {
margin-top: 2px;
color: #6b7280;
font-size: 12px;
}

.search-store-basic-demo__empty {
padding: 24px;
color: #6b7280;
text-align: center;
}

.search-store-basic-demo__more {
width: fit-content;
}

常见问题

Q: 如何自定义搜索结果的显示格式?

A: 使用 SearchResultItem 属性传入自定义组件。

Q: 如何处理搜索性能问题?

A: 调整 debounceTime,使用 React.memo,考虑结果缓存。

Q: 移动端如何优化?

A: 组件自动适配移动端,也可通过 CSS 进一步定制。

Q: 如何支持多语言?

A: 组件内置国际化支持,通过 useUIKit 获取翻译。