useHits hook provides access to the search results (hits) from Algolia.
Import
import { useHits } from 'react-instantsearch';
Parameters
Whether to escape HTML tags in hit string values.
const { items } = useHits({ escapeHTML: false });
Function to transform the hits before rendering.
const { items } = useHits({
transformItems: (items) =>
items.map((item) => ({
...item,
formattedPrice: `$${item.price.toFixed(2)}`,
})),
});
Returns
The array of hits from the current search.
const { items } = useHits();
items.forEach((item) => {
console.log(item.objectID, item.name);
});
Alias for
items (deprecated).Use
items instead. The hits property is deprecated.The complete search results object from Algolia.
const { results } = useHits();
console.log(results?.nbHits);
console.log(results?.processingTimeMS);
The banner to display above the hits (if configured).
const { banner } = useHits();
if (banner) {
return <img src={banner.image.urls[0].url} alt={banner.image.title} />;
}
Function to send events to the Insights API.
const { items, sendEvent } = useHits();
sendEvent('click', items[0], 'Product Clicked');
Function to bind Insights events to HTML elements.
const { items, bindEvent } = useHits();
<div {...bindEvent('click', items[0], 'Product Clicked')}>
{/* ... */}
</div>
Examples
Basic Hits Display
import { useHits } from 'react-instantsearch';
function CustomHits() {
const { items } = useHits();
return (
<div className="hits">
{items.map((item) => (
<div key={item.objectID} className="hit">
<img src={item.image} alt={item.name} />
<h3>{item.name}</h3>
<p>{item.description}</p>
<span>${item.price}</span>
</div>
))}
</div>
);
}
With TypeScript
import { useHits } from 'react-instantsearch';
import type { Hit } from 'instantsearch.js';
interface Product {
objectID: string;
name: string;
description: string;
price: number;
image: string;
brand: string;
}
function ProductHits() {
const { items } = useHits<Product>();
return (
<div className="products">
{items.map((item) => (
<div key={item.objectID}>
<img src={item.image} alt={item.name} />
<h3>{item.name}</h3>
<p>{item.brand}</p>
<p>${item.price.toFixed(2)}</p>
</div>
))}
</div>
);
}
With Highlighting
import { useHits, Highlight } from 'react-instantsearch';
function HighlightedHits() {
const { items } = useHits();
return (
<div className="hits">
{items.map((item) => (
<div key={item.objectID}>
<h3>
<Highlight attribute="name" hit={item} />
</h3>
<p>
<Highlight attribute="description" hit={item} />
</p>
</div>
))}
</div>
);
}
Transform Items
import { useHits } from 'react-instantsearch';
function TransformedHits() {
const { items } = useHits({
transformItems: (items) =>
items.map((item) => ({
...item,
// Add computed fields
formattedPrice: `$${item.price.toFixed(2)}`,
// Add discount calculation
discountPrice: item.discount
? item.price * (1 - item.discount / 100)
: item.price,
})),
});
return (
<div className="hits">
{items.map((item) => (
<div key={item.objectID}>
<h3>{item.name}</h3>
{item.discount ? (
<>
<span className="original-price">{item.formattedPrice}</span>
<span className="discount-price">
${item.discountPrice.toFixed(2)}
</span>
</>
) : (
<span>{item.formattedPrice}</span>
)}
</div>
))}
</div>
);
}
With Insights Events
import { useHits } from 'react-instantsearch';
function HitsWithInsights() {
const { items, sendEvent } = useHits();
const handleClick = (item) => {
sendEvent('click', item, 'Product Clicked');
// Navigate to product page
window.location.href = `/products/${item.objectID}`;
};
return (
<div className="hits">
{items.map((item) => (
<div
key={item.objectID}
onClick={() => handleClick(item)}
style={{ cursor: 'pointer' }}
>
<h3>{item.name}</h3>
<p>{item.description}</p>
</div>
))}
</div>
);
}
With Empty State
import { useHits } from 'react-instantsearch';
function HitsWithEmptyState() {
const { items } = useHits();
if (items.length === 0) {
return (
<div className="empty-state">
<h3>No results found</h3>
<p>Try adjusting your search or filters</p>
</div>
);
}
return (
<div className="hits">
{items.map((item) => (
<div key={item.objectID}>
{/* ... */}
</div>
))}
</div>
);
}
With Results Metadata
import { useHits } from 'react-instantsearch';
function HitsWithMetadata() {
const { items, results } = useHits();
return (
<div>
<div className="results-info">
<p>
{results?.nbHits.toLocaleString()} results found in{' '}
{results?.processingTimeMS}ms
</p>
</div>
<div className="hits">
{items.map((item) => (
<div key={item.objectID}>
{/* ... */}
</div>
))}
</div>
</div>
);
}
Grid Layout
import { useHits } from 'react-instantsearch';
function GridHits() {
const { items } = useHits();
return (
<div className="hits-grid">
{items.map((item) => (
<div key={item.objectID} className="hit-card">
<div className="hit-image">
<img src={item.image} alt={item.name} />
</div>
<div className="hit-content">
<h3>{item.name}</h3>
<p className="brand">{item.brand}</p>
<div className="hit-footer">
<span className="price">${item.price}</span>
{item.rating && (
<span className="rating">⭐ {item.rating}</span>
)}
</div>
</div>
</div>
))}
</div>
);
}
With Banner
import { useHits } from 'react-instantsearch';
function HitsWithBanner() {
const { items, banner } = useHits();
return (
<div>
{banner && (
<div className="banner">
<a href={banner.link.url}>
<img
src={banner.image.urls[0].url}
alt={banner.image.title}
/>
</a>
</div>
)}
<div className="hits">
{items.map((item) => (
<div key={item.objectID}>
{/* ... */}
</div>
))}
</div>
</div>
);
}