# Hooks: useProducts to useProductTypes (/themes/sdk/reference/data/hooks-1)

```ts
import { … } from '@poltura/theme-sdk/data';
```

## `useProducts` [#useproducts]

One page of product cards matching a query, priced for the visitor.

```ts
useProducts(query: ProductQuery, options: SuspenseQueryOptions): SuspenseQueryResult<ProductPage>
useProducts(query: ProductQuery, options?: QueryOptions): QueryResult<ProductPage>
```

Several components asking for the same query share one read. Products only reachable by direct link are left out unless asked for by id or handle.

**Parameters**

- `query: ProductQuery`: Which products, in which order, and which page.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous page while the next loads.

**Returns:** The page of cards with the total count, and the read's status.

**Example**

```tsx
import { useProducts } from '@poltura/theme-sdk/data';

export function NewArrivals() {
  const { data } = useProducts({ sort: 'newest', limit: 4 }, { suspense: true });
  return <ul>{data.items.map((card) => <li key={card.id}>{card.title}</li>)}</ul>;
}
```

## `useInfiniteProducts` [#useinfiniteproducts]

Product cards matching a query, a page at a time, for "load more" and endless lists.

```ts
useInfiniteProducts(query: ProductQuery, options?: Omit<QueryOptions, 'suspense'>): InfiniteQueryResult<ProductPage>
```

**Parameters**

- `query: ProductQuery`: Which products and in which order; `page` is ignored, `limit` is the page size.
- `options?: Omit<QueryOptions, 'suspense'>`: Idling until the inputs are known.

**Returns:** The pages loaded so far and the action that loads the next.

**Example**

```tsx
import { useInfiniteProducts } from '@poltura/theme-sdk/data';

export function EndlessList() {
  const list = useInfiniteProducts({ limit: 12 });
  return (
    <>
      {list.pages.flatMap((page) => page.items).map((card) => <p key={card.id}>{card.title}</p>)}
      {list.hasNextPage ? <button onClick={list.fetchNextPage}>More</button> : null}
    </>
  );
}
```

## `useProduct` [#useproduct]

One product with every variant, option and specification, priced for the visitor.

```ts
useProduct(by: ProductLookup, options: SuspenseQueryOptions): SuspenseQueryResult<Product | null>
useProduct(by: ProductLookup, options?: QueryOptions): QueryResult<Product | null>
```

**Parameters**

- `by: ProductLookup`: The product's URL segment or id.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous product while the next loads.

**Returns:** The product, or null when there is none by that name.

**Example**

```tsx
import { useProduct } from '@poltura/theme-sdk/data';

export function ProductTitle({ handle }: { handle: string }) {
  const { data } = useProduct({ handle }, { suspense: true });
  return data ? <h2>{data.title}</h2> : null;
}
```

## `useCategories` [#usecategories]

The store's categories, in the merchant's order.

```ts
useCategories(query: CategoryQuery | undefined, options: SuspenseQueryOptions): SuspenseQueryResult<readonly Category[]>
useCategories(query?: CategoryQuery, options?: QueryOptions): QueryResult<readonly Category[]>
```

**Parameters**

- `query: CategoryQuery | undefined`: Whose children to list, and how many.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous list while the next loads.

**Returns:** The categories with their images and direct subcategories.

**Example**

```tsx
import { useCategories } from '@poltura/theme-sdk/data';

export function TopCategories() {
  const { data } = useCategories({ parentId: null }, { suspense: true });
  return <nav>{data.map((category) => <a key={category.id} href={category.href}>{category.name}</a>)}</nav>;
}
```

## `useCategory` [#usecategory]

One category with its path, description, image and subcategories.

```ts
useCategory(by: CategoryLookup, options: SuspenseQueryOptions): SuspenseQueryResult<Category | null>
useCategory(by: CategoryLookup, options?: QueryOptions): QueryResult<Category | null>
```

**Parameters**

- `by: CategoryLookup`: The category's URL path or id.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous category while the next loads.

**Returns:** The category, or null when there is none by that name.

**Example**

```tsx
import { useCategory } from '@poltura/theme-sdk/data';

export function CategoryName({ id }: { id: string }) {
  const { data } = useCategory({ id });
  return <span>{data?.name ?? ''}</span>;
}
```

## `useCollections` [#usecollections]

The store's collections.

```ts
useCollections(query: CollectionQuery | undefined, options: SuspenseQueryOptions): SuspenseQueryResult<readonly Collection[]>
useCollections(query?: CollectionQuery, options?: QueryOptions): QueryResult<readonly Collection[]>
```

**Parameters**

- `query: CollectionQuery | undefined`: Which page of collections to list.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous page while the next loads.

**Returns:** The collections with their links.

**Example**

```tsx
import { useCollections } from '@poltura/theme-sdk/data';

export function CollectionLinks() {
  const { data = [] } = useCollections({ limit: 6 });
  return <nav>{data.map((collection) => <a key={collection.id} href={collection.href}>{collection.title}</a>)}</nav>;
}
```

## `useCollection` [#usecollection]

One collection with its description and image.

```ts
useCollection(by: CollectionLookup, options: SuspenseQueryOptions): SuspenseQueryResult<Collection | null>
useCollection(by: CollectionLookup, options?: QueryOptions): QueryResult<Collection | null>
```

**Parameters**

- `by: CollectionLookup`: The collection's URL segment or id.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous collection while the next loads.

**Returns:** The collection, or null when there is none by that name.

**Example**

```tsx
import { useCollection } from '@poltura/theme-sdk/data';

export function CollectionTitle({ handle }: { handle: string }) {
  const { data } = useCollection({ handle }, { suspense: true });
  return <h2>{data?.title ?? ''}</h2>;
}
```

## `useProductAttributes` [#useproductattributes]

Product attributes with their values, by key or as a category offers them for filtering.

```ts
useProductAttributes(by: ProductAttributeLookup, options: SuspenseQueryOptions): SuspenseQueryResult<readonly ProductAttribute[]>
useProductAttributes(by: ProductAttributeLookup, options?: QueryOptions): QueryResult<readonly ProductAttribute[]>
```

**Parameters**

- `by: ProductAttributeLookup`: The attributes' keys, or the category whose attributes to read.
- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous list while the next loads.

**Returns:** The attributes; an unknown key is left out.

**Example**

```tsx
import { useProductAttributes } from '@poltura/theme-sdk/data';

export function MaterialList() {
  const { data = [] } = useProductAttributes({ handles: ['material'] });
  return <ul>{data.flatMap((attribute) => attribute.values).map((value) => <li key={value.id}>{value.label}</li>)}</ul>;
}
```

## `useProductTypes` [#useproducttypes]

The store's product types, such as "T-shirt" or "Gift card".

```ts
useProductTypes(options: SuspenseQueryOptions): SuspenseQueryResult<readonly ProductTypeRef[]>
useProductTypes(options?: QueryOptions): QueryResult<readonly ProductTypeRef[]>
```

**Parameters**

- `options: SuspenseQueryOptions`: Suspense, idling and keeping the previous list while the next loads.

**Returns:** The product types.

**Example**

```tsx
import { useProductTypes } from '@poltura/theme-sdk/data';

export function TypeNames() {
  const { data = [] } = useProductTypes();
  return <p>{data.map((type) => type.name).join(', ')}</p>;
}
```
