# Results

### Purpose

The Results component renders the result cards and pagination components.

### Usage

{% hint style="info" %}
See the [useresults](https://search.docs.reactify.com.au/hooks/useresults "mention") page for more usage details.
{% endhint %}

{% tabs %}
{% tab title="Basic" %}

```tsx
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}
    />
  );
};
```

{% endtab %}

{% tab title="ExampleResultsProductCard" %}

```tsx
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>
    );
  };

```

{% endtab %}

{% tab title="ExampleResultsCalloutCard" %}

```tsx
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>
    );
  };

```

{% endtab %}

{% tab title="ExampleResultsPaginationNumbered" %}

```tsx
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>
    );
  };

```

{% endtab %}

{% tab title="ExampleResultsPaginationNextPrev" %}

```tsx
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>
    );
  };

```

{% endtab %}

{% tab title="ExamplePaginationLoadMore" %}

```tsx
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>
    );
  };

```

{% endtab %}

{% tab title="ExamplePaginationInfiniteScroll" %}

```tsx
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;
  };


```

{% endtab %}
{% endtabs %}

### Props

```typescript
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;
};
```
