# useResults

{% hint style="warning" %}
This hook **must not** be used to render the results grid, the results grid must always be rendered by using the [Results](https://search.docs.reactify.com.au/components/results) component.
{% endhint %}

### Purpose

The useResults hook exposes data for results and result stats.

This can be useful for calculating information from the current results, such as a list of all the collections found in the results.

### Usage

The `loading` field is used to determine if results are currently loading, this is `true` on first load and will change between `true` and `false` as filters, sort options and pagination changes.

The `results` field is an array of the results for the current query.

The `resultStats` field contains metadata about the current query, such as total results, current page, total pages and more.

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

```tsx
import React from "react";
import { useResults, ElasticDocumentType } from "@usereactify/search";

export const ExampleHookUseResults: React.FC = () => {
  const resultsHook = useResults();

  const collections = resultsHook.results
    .map((result) => {
      if (result.type === ElasticDocumentType.Product) {
        return result.collections;
      }

      return [];
    })
    .flat()
    .filter(
      (item, index, self) =>
        self.findIndex((itemNested) => itemNested?.id === item?.id) === index
    );

  return (
    <ul>
      {collections.map((collection) => (
        <li>
          <a href={`/collections/${collection?.handle}`}>{collection?.title}</a>
        </li>
      ))}
    </ul>
  );
};

```

{% endtab %}
{% endtabs %}

### Signature

```typescript
(): {
  /** Equals true until first load has completed */
  loading: boolean;
  /** All of the current results */
  results: ReactivesearchResultProps["data"];
  /** Function for setting the current results */
  setResults: React.Dispatch<
    React.SetStateAction<ReactivesearchResultProps["data"]>
  >;
  /** All of the current result stats */
  resultStats?: ReactivesearchResultProps["resultStats"];
  /** Function for setting the current result stats */
  setResultStats: React.Dispatch<
    React.SetStateAction<ReactivesearchResultProps["resultStats"] | undefined>
  >;
};

Result = ResultProduct | ResultCallout;

ResultProduct = {
  type: "product";
  id: number;
  storefrontId: string;
  title: string;
  description: string;
  vendor: string;
  product_type: string;
  handle: string;
  url: string;
  tags: Array<string>;
  collection_titles: Array<string>;
  price_min: number;
  price_max: number;
  options: Array<string>;
  status: "active" | "archived" | "draft";
  published: boolean;
  published_at: Maybe<string>;
  updated_at: string;
  created_at: string;
  tracks_inventory: boolean;
  image: Maybe<string>;
  images?: Array<ResultProductImage>;
  variants?: Array<ResultProductVariant>;
  presentment_price_ranges?: {
    min_variant_price: Array<{
      amount: number;
      currency_code: string;
    }>;
    max_variant_price: Array<{
      amount: number;
      currency_code: string;
    }>;
  };
  variant_skus?: Array<string>;
  variant_options?: Array<string>;
  collections?: Array<{
    id: number;
    storefrontId: string;
    handle: string;
    title: string;
    position: number;
  }>;
  metafields?: Array<{
    key: string;
    type: string;
    value: string;
    namespace: string;
    value_type: "BOOLEAN" | "INTEGER" | "JSON_STRING" | "STRING";
  }>;
  discount_amount?: number;
  inventory_total?: number;
  published_days: Maybe<number>;
  curations?: Array<{
    id: string;
    hidden: boolean;
    position?: number;
    searchTerm?: string;
    collectionHandle?: string;
  }>;
  related?: Array<ResultProduct>;
  [key: `tags_${string}`]: Array<string> | undefined;
};

ResultProductVariant = {
  id: number;
  storefrontId: string;
  title: string;
  sku: Maybe<string>;
  barcode: Maybe<string>;
  presentment_prices?: Array<{
    price: {
      amount: number;
      currency_code: string;
    };
    compare_at_price: Maybe<{
      amount: number;
      currency_code: string;
    }>;
  }>;
  price: number;
  compare_at_price: Maybe<number>;
  option1: Maybe<string>;
  option2: Maybe<string>;
  option3: Maybe<string>;
  position: number;
  inventory_policy: "CONTINUE" | "DENY";
  inventory_quantity: number;
  available: boolean;
  images?: Array<ResultProductImage>;
}

ResultProductImage = {
  src: string;
  alt: Maybe<string>;
}

ResultCallout = {
  type: "callout";
  key: string;
  callout: {
    id: string;
    type: "standard" | "filler";
    link: string;
    links: Array<Link>;
    title: string;
    content: string;
    textColor: string;
    keywords: Array<string>;
    mobileImage: string;
    mobileVideo: string;
    desktopVideo: string;
    desktopImage: string;
    backgroundColor: string;
    visibility: "desktop" | "mobile" | "all";
    displayColumns: string; // @todo this should be a number
    displayRows: string; // @todo this should be a number
    selectedDates?: {
      end: string;
      start: string;
    };
  };
  /** callouts are always published */
  published: true;
  /** callouts are always attached to one curation */
  curations: Array<ElasticCuration>;
};

ResultStats = {
  time: number;
  hidden: number;
  promoted: number;
  currentPage: number;
  numberOfPages: number;
  numberOfResults?: number;
  displayedResults: number;
}
```
