# Custom data

Data of your own can go out with a message, such as a priority flag, or stay in the composer for your UI only, such as whether a picker is open. The custom data manager, `messageComposer.customDataManager`, keeps both kinds.

>
> **Info:** **Example**
>
> The user marks a message as urgent before sending it:
>
> 1. The UI calls `CustomDataManager.setMessageData({ priority: "high" })`.
> 2. The user sends the message. It goes out with `custom: { priority: "high" }`, and the copy in the message list shows the flag at once.
> 3. The composer clears itself, and the next message starts without the flag.
>

## What it holds

The custom data manager's state is in `customDataManager.state`. It has two fields, both empty objects at first:

| Field     | What it holds                                       | Sent with the message                         | Getter                                 | Setter                               |
| --------- | --------------------------------------------------- | --------------------------------------------- | -------------------------------------- | ------------------------------------ |
| `message` | Data that goes out with the message.                | yes, merged into the message's `custom` field | `customDataManager.customMessageData`  | `CustomDataManager.setMessageData()` |
| `custom`  | Data for your UI, such as whether a picker is open. | never                                         | `customDataManager.customComposerData` | `CustomDataManager.setCustomData()`  |

Declare the fields you use in the `CustomMessageData` and `CustomMessageComposerData` interfaces, as [Data conventions](https://getstream.io/chat/docs/sdk/react-native/state/state-and-entities/data-conventions/) explains:

```ts
import "stream-chat";

declare module "stream-chat" {
  interface CustomMessageData {
    priority?: "high" | "normal";
  }

  interface CustomMessageComposerData {
    priorityPickerOpen?: boolean;
  }
}
```

## Setting data

| To...                      | Call                                     | What happens                                                         |
| -------------------------- | ---------------------------------------- | -------------------------------------------------------------------- |
| send data with the message | `CustomDataManager.setMessageData(data)` | Merges `data` into the `message` field of `customDataManager.state`. |
| keep data for your UI      | `CustomDataManager.setCustomData(data)`  | Merges `data` into the `custom` field of `customDataManager.state`.  |

Both merge at the top level: a key you pass replaces the value it had, and the other keys stay. When the composer is cleared, for example after a send, both fields start empty again.

```ts
const { customDataManager } = channel.messageComposer;

customDataManager.setCustomData({ priorityPickerOpen: true });
customDataManager.setMessageData({ priority: "high" });
```

## How the data goes into the message

When the message is built, the fields of the `message` field of `customDataManager.state` are merged into the message's `custom` field: both in the request the server receives and in the copy the message list shows before the server answers. A [draft](https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/message-composer/#drafts) saves them in its `custom` field too.

- **Loading restores it.** When a draft or a message to edit is loaded into the composer, the `message` field of `customDataManager.state` gets a copy of the draft's or the message's `custom`. The `custom` field starts empty, because its data is never sent.
- **Polls.** A message that carries only a poll carries no custom data, as [Polls](https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/polls/#creating-and-sending-the-poll) explains.
- **Edits.** An edit keeps the fields the message has in `custom`. `CustomDataManager.setMessageData()` merges new values into them. To remove fields, set the `message` field of `customDataManager.state` to the fields to keep: `customDataManager.state.partialNext({ message: { reviewed: true } })`. An empty object removes them all, and the edit then sends an empty `custom`.

>
> **Info:** **Example**
>
> A message has `custom: { priority: "high", reviewed: true }`. The user edits it:
>
> 1. The edit starts, and `customDataManager.customMessageData` holds both fields.
> 2. The UI calls `CustomDataManager.setMessageData({ priority: "low" })`.
> 3. The user saves. The message now has `custom: { priority: "low", reviewed: true }`.
>

To add data that's worked out when the message is sent, use a composition middleware instead, and write the data into the `custom` field of both the request and the local copy. [Composer middleware](https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/composer-middleware/#adding-middleware) shows how to add one.

## Settings

The custom data manager has no settings.

## Used in

- [Composer middleware](https://getstream.io/chat/docs/sdk/react-native/state/writing-messages/composer-middleware/#adding-middleware)
- [Data conventions](https://getstream.io/chat/docs/sdk/react-native/state/state-and-entities/data-conventions/)

---

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