Results
The Result component renders the search results and pagination content.
Purpose
The Results component renders the result cards and pagination components.
Usage
See the useResults page for more usage details.
import React from "react";
import { Results } from "@usereactify/search";
import { ExampleResultCardProduct } from "./ExampleResultCardProduct";
import { ExampleResultCardCallout } from "./ExampleResultCardCallout";
import { ExampleResultPaginationNextPrev } from "./ExampleResultPaginationNextPrev";
import { ExampleResultPaginationNumbered } from "./ExampleResultPaginationNumbered";
import { ExampleResultPaginationLoadMore } from "./ExampleResultPaginationLoadMore";
import { ExampleResultPaginationInfiniteScroll } from "./ExampleResultPaginationInfiniteScroll";
export const Component: React.FC = () => {
return (
<Results
listStyle={{
display: "grid",
gap: "10px",
gridTemplateColumns: "repeat(4, minmax(0, 1fr))",
}}
gridColumns={4}
renderResultCardProduct={ExampleResultCardProduct}
renderResultCardCallout={ExampleResultCardCallout}
renderPaginationNextPrev={ExampleResultPaginationNextPrev}
renderPaginationNumbered={ExampleResultPaginationNumbered}
renderPaginationLoadMore={ExampleResultPaginationLoadMore}
renderPaginationInfiniteScroll={ExampleResultPaginationInfiniteScroll}
/>
);
};
import React from "react";
import { ResultCardProductProps } from "@usereactify/search";
export type ExampleResultCardProductProps = React.ComponentProps<
NonNullable<ResultCardProductProps["render"]>
>;
export const ExampleResultCardProduct: React.FC<ExampleResultCardProductProps> =
(props) => {
return (
<div ref={props.itemRef} className="rs__result-card-product">
<a
className="rs__result-card-product__link"
onClick={props.handleClick}
href={`/products/${props.product.handle}`}
>
{props.product.image && (
<img
className="rs__result-card-product__image"
src={props.product.image}
width="100%"
/>
)}
<span className="rs__result-card-product__title">
{props.product.title}
</span>
</a>
<span className="rs__result-card-product__price">
{props.formattedPrice}
</span>
{props.onSale && (
<span
className="rs__result-card-product__price-sale"
style={{
textDecoration: "line-through",
}}
>
{props.formattedCompareAtPrice}
</span>
)}
</div>
);
};
import React from "react";
import { ResultCardCalloutProps } from "@usereactify/search";
export type ExampleResultCardCalloutProps = React.ComponentProps<
NonNullable<ResultCardCalloutProps["render"]>
>;
export const ExampleResultCardCallout: React.FC<ExampleResultCardCalloutProps> =
(props) => {
const styleProp = React.useMemo<React.HTMLAttributes<HTMLElement>["style"]>(
() => ({
gridRow: `span ${props.callout.displayRows ?? 1}`,
gridColumn: `span ${props.callout.displayColumns ?? 1}`,
}),
[props.callout]
);
return (
<div
className="rs__result-card-callout"
ref={props.itemRef}
style={styleProp}
>
<a
className="rs__result-card-callout__link"
onClick={props.handleClick}
{...(!!props.callout.link && { href: props.callout.link })}
>
{props.callout.desktopImage && (
<img
className="rs__result-card-callout__image"
src={props.callout.desktopImage}
width="100%"
/>
)}
<span className="rs__result-card-callout__title">
{props.callout.title}
</span>
</a>
</div>
);
};
import React from "react";
import { ResultPaginationNumberedProps } from "@usereactify/search";
export type ExampleResultPaginationNumberedProps = React.ComponentProps<
NonNullable<ResultPaginationNumberedProps["render"]>
>;
export const ExampleResultPaginationNumbered: React.FC<ExampleResultPaginationNumberedProps> =
(props) => {
return (
<nav className="rs__pagination__nav">
{props.currentPage > 0 && (
<a
className="rs__pagination__prev-link"
rel="prev"
href={props.buildPagePath(props.currentPage)}
onClick={(event) => props.handlePreviousPage(event)}
>
{"Prev"}
</a>
)}
{!props.pagesToShow.includes(0) && (
<a
className="rs__pagination__pagenumber-link"
href={props.buildPagePath(1)}
onClick={(event) => props.handlePageChange(0, event)}
rel={0 === props.currentPage - 1 ? `prev` : undefined}
>
{"1"}
</a>
)}
{!props.pagesToShow.includes(1) && <span>...</span>}
{props.pagesToShow.map((page) =>
page === props.currentPage ? (
<span className="rs__pagination__pagenumber-active" key={page + 1}>
{page + 1}
</span>
) : (
<a
className="rs__pagination__pagenumber-link"
key={page + 1}
href={props.buildPagePath(page + 1)}
onClick={(event) => props.handlePageChange(page, event)}
rel={
page === props.currentPage + 1
? `next`
: page === props.currentPage - 1
? `prev`
: undefined
}
>
{page + 1}
</a>
)
)}
{!props.pagesToShow.includes(props.totalPages - 2) && <span>...</span>}
{!props.pagesToShow.includes(props.totalPages - 1) && (
<a
className="rs__pagination__pagenumber-link"
href={props.buildPagePath(props.totalPages)}
onClick={(event) =>
props.handlePageChange(props.totalPages - 1, event)
}
rel={
props.totalPages - 1 === props.currentPage + 1
? `next`
: props.totalPages - 1 === props.currentPage - 1
? `prev`
: undefined
}
>
{props.totalPages}
</a>
)}
{props.currentPage + 1 < props.totalPages && (
<a
className="rs__pagination__next-link"
rel="next"
href={props.buildPagePath(props.currentPage + 2)}
onClick={(event) => props.handleNextPage(event)}
>
{"Next"}
</a>
)}
</nav>
);
};
import React from "react";
import { ResultPaginationNextPrevProps } from "@usereactify/search";
export type ExampleResultPaginationNextPrevProps = React.ComponentProps<
NonNullable<ResultPaginationNextPrevProps["render"]>
>;
export const ExampleResultPaginationNextPrev: React.FC<ExampleResultPaginationNextPrevProps> =
(props) => {
return (
<nav className="rs__pagination__nav">
{props.hasPreviousPage && (
<a
className="rs__pagination__prev-link"
rel="prev"
onClick={props.handlePreviousPage}
href={props.buildPagePath(props.actualCurrentPage - 1)}
>
{"Prev"}
</a>
)}
{props.hasNextPage && (
<a
className="rs__pagination__next-link"
rel="next"
onClick={props.handleNextPage}
href={props.buildPagePath(props.actualCurrentPage + 1)}
>
{"Next"}
</a>
)}
</nav>
);
};
import React from "react";
import { ResultPaginationLoadMoreProps } from "@usereactify/search";
export type ExampleResultPaginationLoadMoreProps = React.ComponentProps<
NonNullable<ResultPaginationLoadMoreProps["render"]>
>;
export const ExampleResultPaginationLoadMore: React.FC<ExampleResultPaginationLoadMoreProps> =
(props) => {
return (
<button
className="rs__pagination__loadmore-button"
onClick={() => props.handleLoadMore()}
disabled={!props.hasMore}
>
{"Load more"}
</button>
);
};
import React from "react";
import { ResultPaginationInfiniteScrollProps } from "@usereactify/search"";
export type ExampleResultPaginationInfiniteScrollProps = React.ComponentProps<
NonNullable<ResultPaginationInfiniteScrollProps["render"]>
>;
export const ExampleResultPaginationInfiniteScroll: React.FC<ExampleResultPaginationInfiniteScrollProps> =
(props) => {
if (props.loading) {
return (
<div className="rs__pagination__infinitescroll-loading">
{"Loading..."}
</div>
);
}
return null;
};
Props
type ResultsProps = {
/** Style prop for the list wrapper */
listStyle?: React.HTMLAttributes<HTMLElement>["style"];
/** Classname prop for the list wrapper */
listClassName?: string;
/** Render method called when an error occurs */
renderError?: React.FC<{ error: ReactivesearchError }>;
/** Render method called while loading for the first time */
renderLoading?: React.FC;
/** Render method called when no results are found */
renderNoResults?: React.FC;
/** Render method called once for each product result */
renderResultCardProduct?: React.FC<
ReturnType<typeof useProductPrice> & {
pagePosition: number;
document: ResultProduct;
product: ResultProduct;
itemRef: (node?: Element | null) => void;
handleClick: () => void;
}
>;
/** Render method called once for each callout result */
renderResultCardCallout?: React.FC<{
pagePosition: number;
document: ResultCallout;
callout: ResultCallout["callout"];
itemRef: (node?: Element | null) => void;
handleClick: () => void;
}>;
/** Render method called for pagination type "pagination" */
renderPaginationNumbered?: React.FC<ReturnType<typeof usePagination>>;
/** Render method called for pagination type "next_prev" */
renderPaginationNextPrev?: React.FC<ReturnType<typeof usePagination>>;
/** Render method called for pagination type "load_more" */
renderPaginationLoadMore?: React.FC<ReturnType<typeof usePaginationLoadable>>;
/** Render method called for pagination type "infinite_scroll" */
renderPaginationInfiniteScroll?: React.FC<
ReturnType<typeof usePaginationLoadable>
>;
/** Used to determine which filler callouts to use when there is an uneven grid */
gridColumns?: number;
/** Advanced Usage: Override the default amount of results per page */
pageSize?: number;
/** Advanced Usage: Override the default scrollTarget used to determine when infinite load should be triggered (infinite scroll) */
infiniteScrollContainer?: React.ComponentProps<
typeof ReactiveList
>["scrollTarget"];
/** Advanced Usage: Provide a specific result position to trigger loading more results (infinite scroll) */
infiniteScrollPosition?: number;
/** Advanced Usage: Shows subsequent loading states after initial results are loaded */
showSubsequentLoadingStates?: boolean;
};
Last updated