> Portal Navigation:
> 
> - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version.
> - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages).
> - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`).
> - If a reference page seems to be missing its schema (parameters, return types, or type definitions), append `?schema=true` to its `.md` URL (e.g. `https://dev.wix.com/docs/contexts/contexts/stores/category-info/use-category-info-context.md?schema=true`).
> - Top-level index of all portals: https://dev.wix.com/docs/llms.txt
> - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt

## Resource: Introduction

## Article: Introduction

## Article Link: https://dev.wix.com/docs/contexts/contexts/bookings/locations/introduction.md

## Article Content:

# About the Locations Context

The Locations context provides access to the business locations where the site's Wix Bookings services take place, and to the location a site visitor selected. Use it to list the locations, let site visitors select a location to filter services by, and show the list's loading and error states.

A component can use the context when it's placed in:

- A page, container, or section that the **Locations** [Data Source](https://dev.wix.com/docs/studio-two/code-your-site/code-model/data-sources/about-data-sources.md) is attached to, for the business locations of the site's visible services.

Anywhere else, the context's hook throws an error.

For more about business locations, see the [Locations API](https://dev.wix.com/docs/api-reference/business-management/locations/introduction.md).

## How values change

The page URL holds the selected location in the `location` query parameter. So a selection stays when the page reloads, and site visitors can share it as a link. When the page opens with a selection, `selectedLocationId` holds it right away, before the locations finish loading. `selectLocation()` changes the parameter, and the selection values update with it. A Services context on the same page reads the same parameter, so it lists only the services at the selected location. When the selected location is `'OTHER_LOCATIONS'`, it lists only the services at custom addresses and customers' locations.

## Loading and errors

While the locations load, `isLoading` is `true`, the lists are empty, and `selectLocation()` does nothing. When the locations fail to load, `hasError` is `true`, and the lists stay empty until `refetch()` loads them again.

## Usage

`useLocationsContext()` returns an object with the context's properties and functions.

```tsx
import { useLocationsContext } from '@wix/bookings/context/locations';

function MyComponent() {
  const { locationItems, selectedLocationId, selectLocation } = useLocationsContext();
  // ...
}
```

### Add location tabs

This component shows a tab for each location, an All locations tab, and an Other locations tab when some services take place at a custom address or at the customer's location. It shows no tabs when site visitors have only one choice, and a button to load the locations again when they fail to load.

```tsx
import { useLocationsContext } from '@wix/bookings/context/locations';

function LocationTabs() {
  const {
    locationItems,
    selectedLocationId,
    hasOtherLocations,
    hasMultipleLocations,
    hasError,
    refetch,
    selectLocation,
  } = useLocationsContext();

  if (hasError) {
    return <button onClick={() => refetch()}>Load locations again</button>;
  }

  if (!hasMultipleLocations) {
    return null;
  }

  return (
    <div role="tablist">
      <button
        role="tab"
        aria-selected={selectedLocationId === null}
        onClick={() => selectLocation(null)}
      >
        All locations
      </button>
      {locationItems.map(({ locationId, locationName, isSelected }) =>
        locationId ? (
          <button
            key={locationId}
            role="tab"
            aria-selected={isSelected}
            onClick={() => selectLocation(locationId)}
          >
            {locationName ?? locationId}
          </button>
        ) : null,
      )}
      {hasOtherLocations && (
        <button
          role="tab"
          aria-selected={selectedLocationId === 'OTHER_LOCATIONS'}
          onClick={() => selectLocation('OTHER_LOCATIONS')}
        >
          Other locations
        </button>
      )}
    </div>
  );
}
```