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>
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}
/>
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