# Location

The user can share where they are in a message: once, as a static location, or for a while, as a live location that follows them. The location composer, `messageComposer.locationComposer`, holds the location to share until it's sent.

>
> **Info:** **Example**
>
> The user wants to show the channel where they are for the next 15 minutes:
>
> 1. The user's app reads the device's position and gives it to the location composer, with a duration of 15 minutes.
> 2. The composer sends a message that carries the location.
> 3. For the next 15 minutes, the user's app sends each new position of the device to the server.
> 4. The other members' apps receive each new position as an update of that message, and their map moves with the user. After 15 minutes, the updates stop.
>

The SDK has no location picker and doesn't read the device's position. Your app reads it and gives it to the location composer, as [Location sharing](https://getstream.io/chat/docs/sdk/react-native/features/rich-content/location-sharing/) explains.

## What it holds

The location composer's state is in `locationComposer.state`. Its one field, `location`, is the location to share, or `null` when there is none:

| Field                  | What it holds                                                                                       | Set by                                                    |
| ---------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `latitude`             | The position's latitude.                                                                            | your app                                                  |
| `longitude`            | The position's longitude.                                                                           | your app                                                  |
| `durationMs`           | For a live location: how long to share it, in milliseconds. Absent for a static location.           | your app                                                  |
| `end_at`               | Only while a message with a live location is edited: when its sharing ends, taken from the message. | the edited message                                        |
| `message_id`           | The id of the message that will carry the location, which is the composer's `id`.                   | the composer                                              |
| `created_by_device_id` | The device the location is shared from.                                                             | the composer, from the `getDeviceId` [setting](#settings) |

The composer adds `message_id` and `created_by_device_id` itself. By default, the device id is a random one, new for each composer. To keep one id per device, set `messageComposer.location.getDeviceId` in `client.config` to return an id your app stores, as [Settings](#settings) shows.

A new live location gets its `end_at` when the message is sent: the send time plus `durationMs`. The message then carries it in `message.shared_location.end_at`. While that message is edited, the composer keeps its `end_at`, so editing doesn't extend the sharing.

Two getters read the location:

| Getter                           | Returns                                                                                                                                                                                                                                        | Use it to                                         |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
| `locationComposer.location`      | The location as the composer holds it, or `null`.                                                                                                                                                                                              | show what's being shared                          |
| `locationComposer.validLocation` | The location the composer will send, or `null` when it can't be sent yet: a field is missing, or `durationMs` is shorter than the `minShareDurationMs` [setting](#settings). `MessageComposer.sendLocation()` sends nothing while it's `null`. | enable sharing only when the location can be sent |

## Sharing a location

What a location picker needs, and the call for each:

| To...                                     | Call                                                            | What happens                                                                                                                                                                                                                                      |
| ----------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| set the location to share                 | `LocationComposer.setData({ latitude, longitude })`             | Sets the location, with the composer's id and the device id. Does nothing while [location sharing is off](#when-location-sharing-is-on), or when `latitude` or `longitude` is missing.                                                            |
| set a live location                       | `LocationComposer.setData({ latitude, longitude, durationMs })` | The same, for a location shared for `durationMs` milliseconds.                                                                                                                                                                                    |
| send the location as a message of its own | `MessageComposer.sendLocation()`                                | Sends a message that carries only the location, then removes the location from the composer and gives the composer a new `id`. Text and attachments stay. Does nothing in a thread composer, or while `locationComposer.validLocation` is `null`. |
| remove the location                       | `LocationComposer.initState()`                                  | Sets `location` back to `null`.                                                                                                                                                                                                                   |

```ts
const composer = channel.messageComposer;

composer.locationComposer.setData({
  durationMs: 15 * 60 * 1000,
  latitude: 50.0875,
  longitude: 14.4213,
});

await composer.sendLocation();
```

`MessageComposer.sendLocation()` doesn't add the message to the list at once: the message appears when the server's copy arrives. When the request fails, it publishes an `api:location:create:failed` notification and throws.

A valid location also counts as content for `MessageComposer.send()`, which then sends it as the message's `shared_location`, together with the text and attachments. The SDK's composer shows no preview of a location it holds.

Once a live location is shared, its updates are not the composer's job. [Location sharing](https://getstream.io/chat/docs/sdk/react-native/features/rich-content/location-sharing/#keeping-a-live-location-current) explains how `LiveLocationManager` sends them and how the sharing stops.

## When location sharing is on

Location sharing is on while `messageComposer.config.location.enabled` is `true`. That's when both the `location.enabled` setting in `client.config` and the channel type's `shared_locations` setting are on. While sharing is off, `LocationComposer.setData()` ignores the location it's given, so the composer has no new location to send.

## Settings

Set them for every composer in `client.config`, under `messageComposer.location`:

```ts
import { StreamChat } from "stream-chat";

const client = StreamChat.getInstance("YOUR_API_KEY");

const deviceId = "my-app-device-id"; // for example, an id your app keeps for this device

client.config.set({
  messageComposer: {
    location: {
      getDeviceId: () => deviceId,
      minShareDurationMs: 5 * 60 * 1000,
    },
  },
});
```

The location composer has no setters. To change a setting for one composer only, patch that composer's configuration, for example `channel.messageComposer.updateConfig({ location: { enabled: false } })`.

| Setting              | Default                      | What it does                                                                                                                                                                                                                                                                                                                              |
| -------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`            | `true`                       | `false` turns off location sharing. Combined with the channel type's `shared_locations` setting.                                                                                                                                                                                                                                          |
| `getDeviceId`        | a new random id per composer | Returns the id of the device the location is shared from. The default gives each composer a different id: to keep one id per device, return an id your app stores. A composer calls it once, when it's created, as [Settings read once](https://getstream.io/chat/docs/sdk/react-native/state/state-and-entities/configuration/#settings-read-once) explains. |
| `minShareDurationMs` | `60000`, one minute          | The shortest `durationMs` a live location can have. A location with a shorter one isn't valid, so it isn't sent.                                                                                                                                                                                                                          |

See [Location sharing](https://getstream.io/chat/docs/sdk/react-native/features/rich-content/location-sharing/) for the feature.

## Used in

- [Location sharing](https://getstream.io/chat/docs/sdk/react-native/features/rich-content/location-sharing/)

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/location/](https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/location/).