Results
The ResultStack component renders the search results and pagination content.
Purpose
The Results component renders the result cards and pagination components.
Usage
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))",
}}
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;
product: ElasticProduct;
document: ElasticProduct;
itemRef: (node?: Element | null) => void;
handleClick: () => void;
}
>;
/** Render method called once for each callout result */
renderResultCardCallout?: React.FC<{
pagePosition: number;
document: ElasticCallout;
callout: ElasticCallout["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>
>;
/** Define which fields should be included in results data */
// includeFields?: Array<string>;
/** Define which fields should be excluded from results data */
// excludeFields?: Array<string>;
/** 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