# useSelector

**Category:** Common/Hooks

## Design

### Description

`useSelector` is a custom hook designed for React applications that doesn't use MobX for state management. Its primary purpose is to simplify the process of getting updated values from the MobX state within functional components. By creating a reactive binding between a MobX selector function and a React component, useSelector allows components to subscribe to changes in specific parts of the MobX state and automatically update when those parts change.

You should use useSelector when you want to access and use specific data from the MobX store in a React functional component.

WixPatterns uses internally Mobx state management library.
It also exposes Mobx state with custom hooks like `useTableCollection` and `useWidgetsFormContext`.
For applications that doesn't use MobX and want the values from MobX to be updated, and not staled, the `useSelector` custom hook is for the rescue.


```tsx
import { useSelector } from '@wix/patterns';
```

### Basic

Add a filter and see the value of title changes

```tsx
import { Avatar, Page } from '@wix/design-system';
import React from 'react';
import { CollectionPage } from '@wix/patterns/page';
import {
  Table,
  useSelector,
  stringsArrayFilter,
  idNameArrayFilter,
  CollectionToolbarFilters,
  MultiSelectCheckboxFilter,
  useTableCollection,
  useStaticListFilterCollection,
  Filter,
  SingleSelectFilter,
  OffsetQuery,
} from '@wix/patterns';
import { contacts } from '@wix/crm';
import { subDays } from 'date-fns';

interface Duration {
  id: string;
  name: string;
  days: number | null;
}

type ContactsFilters = {
  lastActivity: Filter<Duration[]>;
  level: Filter<string[]>;
};

function UseSelectorExample() {

  const state = useTableCollection<contacts.Contact, ContactsFilters>({
    queryName: 'contacts-useSelector',
    fetchData: (query: OffsetQuery<ContactsFilters>) => {
      const { limit, offset, search, filters } = query;

      let queryBuilder = contacts.queryContacts().limit(limit).skip(offset);

      if (search) {
        queryBuilder = queryBuilder.startsWith('info.name.first', search);
      }

      if (filters.level) {
        queryBuilder = queryBuilder.in('info.jobTitle', filters.level);
      }

      const lastActivityDays = filters.lastActivity?.[0]?.days;
      if (lastActivityDays) {
        queryBuilder = queryBuilder.gt(
          'lastActivity.activityDate',
          subDays(new window.Date(), lastActivityDays),
        );
      }

      return queryBuilder.find().then(({ items = [], totalCount: total }) => ({
        items,
        total,
      }));
    },
    itemName: (item) => `${item.info?.name?.first} ${item.info?.name?.last}`,
    fetchErrorMessage: () => 'Error fetching contacts',
    filters: {
      level: stringsArrayFilter(),
      lastActivity: idNameArrayFilter(),
    },
  });

  const collection = state.collection;

  const lastActivityCollection = useStaticListFilterCollection(
    collection.filters.lastActivity,
    [
      { id: 'w', name: 'Week', days: 7 },
      { id: 'm', name: 'Month', days: 30 },
      { id: 'y', name: 'Year', days: 365 },
      { id: 'o', name: 'Other', days: null },
    ],
  );

  const levelsCollection = useStaticListFilterCollection(
    collection.filters.level,
    [
      'Beginner',
      'Amateur',
      'Semi-Pro',
      'Professional',
      'World Class',
      'Legendary',
      'Ultimate',
    ],
  );

  // hasActiveFilters will have the updated value from MobX store
  const hasActiveFilters = useSelector(() => collection.query.hasActiveFilters);

  return (
    <CollectionPage height="400px">
      <CollectionPage.Header
        title={{ text: `hasActiveFilters value:${hasActiveFilters}` }}
      />
      <Page.Content>
        <Table
          state={state}
          filters={
            <CollectionToolbarFilters>
              <MultiSelectCheckboxFilter
                accordionItemProps={{ label: 'Level' }}
                popoverProps={{ appendTo: 'window' }}
                filter={collection.filters.level!}
                collection={levelsCollection}
                renderItem={(level) => ({ title: level })}
              />
              <SingleSelectFilter
                filter={collection.filters.lastActivity!}
                placeholder="Select Last Activity"
                accordionItemProps={{ label: 'Last Activity' }}
                collection={lastActivityCollection}
              />
            </CollectionToolbarFilters>
          }
          columns={[
            {
              title: '',
              width: '50px',
              render: (contact) => (
                <Avatar
                  name={`${contact.info?.name?.first} ${contact.info?.name?.last}`}
                  imgProps={{ src: contact.info?.picture?.image }}
                />
              ),
            },
            {
              title: 'Name',
              width: '250px',
              render: (contact) =>
                `${contact.info?.name?.first} ${contact.info?.name?.last}`,
            },
            {
              title: 'Level',
              render: (contact) => contact.info?.jobTitle,
            },
            {
              title: 'Last Activity',
              render: (contact) =>
                contact.lastActivity?.activityDate?.toLocaleString(),
            },
          ]}
        />
      </Page.Content>
    </CollectionPage>
  );
}
```

