React集成 #
安装 #
bash
npm install algoliasearch react-instantsearch
基本配置 #
创建搜索组件 #
jsx
import algoliasearch from 'algoliasearch';
import { InstantSearch, SearchBox, Hits } from 'react-instantsearch';
const client = algoliasearch('APP_ID', 'SEARCH_KEY');
function App() {
return (
<InstantSearch indexName="products" searchClient={client}>
<SearchBox />
<Hits hitComponent={Hit} />
</InstantSearch>
);
}
function Hit({ hit }) {
return (
<div className="hit">
<h3>{hit.name}</h3>
<p>${hit.price}</p>
</div>
);
}
核心组件 #
InstantSearch #
jsx
<InstantSearch
indexName="products"
searchClient={client}
initialUiState={{
products: {
query: 'iphone',
page: 1
}
}}
>
{/* 子组件 */}
</InstantSearch>
SearchBox #
jsx
<SearchBox
placeholder="搜索商品..."
autoFocus={true}
searchAsYouType={true}
showReset={true}
showSubmit={true}
showLoadingIndicator={true}
classNames={{
root: 'search-box',
input: 'search-input',
submit: 'search-submit',
reset: 'search-reset'
}}
/>
Hits #
jsx
<Hits
hitComponent={({ hit }) => (
<div className="hit">
<img src={hit.image} alt={hit.name} />
<h3>{hit.name}</h3>
<p>${hit.price}</p>
</div>
)}
/>
分页组件 #
Pagination #
jsx
import { Pagination } from 'react-instantsearch';
<Pagination
showFirst={true}
showPrevious={true}
showNext={true}
showLast={true}
padding={2}
/>
InfiniteHits #
jsx
import { InfiniteHits } from 'react-instantsearch';
<InfiniteHits
hitComponent={Hit}
showPrevious={true}
/>
过滤组件 #
RefinementList #
jsx
import { RefinementList } from 'react-instantsearch';
<RefinementList
attribute="brand"
searchable={true}
searchablePlaceholder="搜索品牌"
showMore={true}
showMoreLimit={20}
limit={5}
/>
Menu #
jsx
import { Menu } from 'react-instantsearch';
<Menu
attribute="category"
showMore={true}
limit={5}
/>
ToggleRefinement #
jsx
import { ToggleRefinement } from 'react-instantsearch';
<ToggleRefinement
attribute="inStock"
label="仅显示有货"
value={true}
/>
RangeInput #
jsx
import { RangeInput } from 'react-instantsearch';
<RangeInput
attribute="price"
min={0}
max={2000}
precision={0}
/>
排序组件 #
SortBy #
jsx
import { SortBy } from 'react-instantsearch';
<SortBy
items={[
{ value: 'products', label: '相关度' },
{ value: 'products_price_asc', label: '价格升序' },
{ value: 'products_price_desc', label: '价格降序' }
]}
/>
状态组件 #
CurrentRefinements #
jsx
import { CurrentRefinements } from 'react-instantsearch';
<CurrentRefinements
transformItems={items =>
items.map(item => ({
...item,
label: item.attribute === 'brand' ? '品牌' : item.label
}))
}
/>
ClearRefinements #
jsx
import { ClearRefinements } from 'react-instantsearch';
<ClearRefinements
excludedAttributes={['query']}
/>
Stats #
jsx
import { Stats } from 'react-instantsearch';
<Stats
translations={{
resultsText: '{nbHits} 个结果'
}}
/>
自定义组件 #
useSearchBox Hook #
jsx
import { useSearchBox } from 'react-instantsearch';
function CustomSearchBox() {
const { query, refine } = useSearchBox();
return (
<input
type="text"
value={query}
onChange={e => refine(e.target.value)}
placeholder="搜索..."
/>
);
}
useHits Hook #
jsx
import { useHits } from 'react-instantsearch';
function CustomHits() {
const { hits } = useHits();
return (
<div className="hits">
{hits.map(hit => (
<div key={hit.objectID} className="hit">
<h3>{hit.name}</h3>
<p>${hit.price}</p>
</div>
))}
</div>
);
}
useInstantSearch Hook #
jsx
import { useInstantSearch } from 'react-instantsearch';
function SearchStatus() {
const { results } = useInstantSearch();
if (!results) return null;
if (results.nbHits === 0) {
return <p>没有找到结果</p>;
}
return (
<p>
找到 {results.nbHits} 个结果,
耗时 {results.processingTimeMS}ms
</p>
);
}
完整示例 #
jsx
import algoliasearch from 'algoliasearch';
import {
InstantSearch,
SearchBox,
Hits,
Pagination,
RefinementList,
CurrentRefinements,
ClearRefinements,
SortBy,
Stats,
Configure
} from 'react-instantsearch';
import 'instantsearch.css/themes/algolia.css';
const client = algoliasearch('APP_ID', 'SEARCH_KEY');
function SearchPage() {
return (
<InstantSearch indexName="products" searchClient={client}>
<Configure
hitsPerPage={12}
attributesToHighlight={['name', 'description']}
/>
<div className="search-container">
<aside className="filters">
<h3>筛选</h3>
<ClearRefinements />
<h4>品牌</h4>
<RefinementList attribute="brand" searchable />
<h4>分类</h4>
<RefinementList attribute="category" />
<h4>价格</h4>
<RefinementList attribute="price_range" />
</aside>
<main className="results">
<div className="search-header">
<SearchBox placeholder="搜索商品..." />
<SortBy
items={[
{ value: 'products', label: '相关度' },
{ value: 'products_price_asc', label: '价格升序' },
{ value: 'products_price_desc', label: '价格降序' }
]}
/>
</div>
<div className="search-info">
<Stats />
<CurrentRefinements />
</div>
<Hits hitComponent={ProductHit} />
<Pagination />
</main>
</div>
</InstantSearch>
);
}
function ProductHit({ hit }) {
return (
<article className="product-card">
<img src={hit.image} alt={hit.name} />
<div className="product-info">
<h3>{hit.name}</h3>
<p className="brand">{hit.brand}</p>
<p className="price">${hit.price}</p>
<p className="rating">★ {hit.rating}</p>
</div>
</article>
);
}
export default SearchPage;
样式定制 #
CSS类名 #
jsx
<SearchBox
classNames={{
root: 'my-search-box',
form: 'my-search-form',
input: 'my-search-input',
submit: 'my-search-submit',
reset: 'my-search-reset'
}}
/>
自定义样式 #
css
.my-search-box {
margin-bottom: 20px;
}
.my-search-input {
width: 100%;
padding: 12px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 16px;
}
.my-search-input:focus {
border-color: #5468ff;
outline: none;
}
总结 #
React集成要点:
| 要点 | 说明 |
|---|---|
| 核心组件 | InstantSearch, SearchBox, Hits |
| 过滤组件 | RefinementList, Menu, ToggleRefinement |
| 分页组件 | Pagination, InfiniteHits |
| Hooks | useSearchBox, useHits, useInstantSearch |
| 样式 | classNames属性,自定义CSS |
接下来,让我们学习 Vue集成。
最后更新:2026-03-28