# Hooks (/themes/sdk/reference/listing/hooks)

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

## `useListingFilters` [#uselistingfilters]

The filters of the product list the component sits in: its groups, the shopper's selection and the actions that change it.

```ts
useListingFilters(): ListingFiltersState
```

The selection lives in the page address, so a filtered list renders on the server and can be shared. Changing it returns to the first page.

**Returns:** The filter state; outside a product list it has no groups and its actions do nothing.

**Example**

```tsx
import { FilterGroup, useListingFilters } from '@poltura/theme-sdk/listing';

export function ThemeFilters() {
  const filters = useListingFilters();
  return (
    <aside>
      {filters.groups.map((group) => (
        <FilterGroup
          key={group.id}
          group={group}
          onToggle={(optionId) => filters.toggle(group.id, optionId)}
          onPriceChange={filters.setPriceRange}
        />
      ))}
    </aside>
  );
}
```

## `useListing` [#uselisting]

The product list the component sits in: its heading, the cards of the current page, the sort, the paging and the merchant's grid choices.

```ts
useListing(): ListingState
```

Sort and page live in the page address, so a listing renders on the server and can be shared.

**Returns:** The listing; outside a collection, category or search page it has no products and its actions do nothing.

**Example**

```tsx
import { ListingEmpty, ListingHeader, ProductGrid, useListing } from '@poltura/theme-sdk/listing';

export function ThemeListing() {
  const listing = useListing();
  return (
    <>
      <ListingHeader header={listing.header} />
      {listing.isEmpty ? <ListingEmpty /> : <ProductGrid cards={listing.products} columns={listing.layout.columns} />}
    </>
  );
}
```
