# Channel details contexts

> **Info:** This is release candidate documentation for **Stream Chat React Native SDK v10**. For the latest stable version, see the [latest version (v9)](https://getstream.io/chat/docs/sdk/react-native/).

The contexts of channel details. `ChannelDetailsContextProvider` holds the channel every part of the screen reads; you render it. The forms and lists render the other providers themselves, each holding a search source or a store. This page lists each provider's props and value. The hooks that read them are on [Channel details hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/channel-details-hooks/).

## Best practices

- Render `ChannelDetailsContextProvider` around `ChannelDetails`, and around every screen of your own that renders a form or a list of channel details, with the same channel.
- Don't render the list providers yourself to use a list, since the lists render their own. Render a provider when you build a list of your own on its search source, or pass `searchSource` to the list.
- Create a search source of your own once, with `useState(() => ...)`, and activate it. The providers use the source they get as it is.
- Read a source's results with `useStateStore(searchSource.state, selector)` and a selector at module scope.

## Overview

| Provider                            | Rendered by              | Value                                                          | Hook                                    |
| ----------------------------------- | ------------------------ | -------------------------------------------------------------- | --------------------------------------- |
| `ChannelDetailsContextProvider`     | your app                 | `{ channel, closeModals, signalStore }`                        | `useChannelDetailsContext()`            |
| `ChannelEditDetailsProvider`        | `ChannelEditDetailsForm` | `{ store, submit, compressImageQuality, doFileUploadRequest }` | `useChannelEditDetailsContext()`        |
| `ChannelAddMembersProvider`         | `ChannelAddMembersForm`  | `{ searchSource, selectionStore, submit }`                     | `useChannelAddMembersContext()`         |
| `ChannelMemberListProvider`         | `ChannelMemberList`      | `{ searchSource }`                                             | `useChannelMemberListContext()`         |
| `ChannelPinnedMessageListProvider`  | `PinnedMessageList`      | `{ searchSource }`                                             | `useChannelPinnedMessageListContext()`  |
| `ChannelMediaListProvider`          | `MediaList`              | `{ searchSource }`                                             | `useChannelMediaListContext()`          |
| `ChannelFileAttachmentListProvider` | `FileAttachmentList`     | `{ searchSource }`                                             | `useChannelFileAttachmentListContext()` |

Every hook throws outside its provider. The edit and add members providers read the channel from `ChannelDetailsContextProvider`, so they need it around them. The list providers take the channel as a prop. Each context is also exported, as `ChannelDetailsContext`, `ChannelEditDetailsContext` and so on.

## ChannelDetailsContextProvider

| Prop       | Type        | Default  | Description                   |
| ---------- | ----------- | -------- | ----------------------------- |
| `channel`  | `Channel`   | required | The channel the screens show. |
| `children` | `ReactNode` |          | The screen.                   |

`ChannelDetailsContextValue`:

| Value         | Type          | Description                                                                                                                         |
| ------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `channel`     | `Channel`     | The channel passed to the provider.                                                                                                 |
| `closeModals` | `() => void`  | Closes every modal channel details opened inside this provider, such as the member list. Call it before you navigate away from one. |
| `signalStore` | `SignalStore` | The store `closeModals()` signals through. Its `state` holds `signal`, which turns `true` and back to `false` on each call.         |

The value changes when the provider gets another channel. A new channel instance under the same `cid` counts as another channel.

## ChannelEditDetailsProvider

`ChannelEditDetailsForm` renders it around the edit form, with the form's `compressImageQuality` and `doFileUploadRequest`. It's also a notification target in the `channel-details` panel, so the notifications of saving show in the form.

`ChannelEditDetailsProviderProps`:

| Prop                   | Type                      | Default                | Description                                                                                                |
| ---------------------- | ------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------- |
| `compressImageQuality` | `number`                  |                        | From 0 to 1, the quality a picked or taken image is compressed to. Without it, the image isn't compressed. |
| `doFileUploadRequest`  | `GlobalFileUploadRequest` | `client.uploadImage()` | Uploads the new image and returns `{ file }`, the URL to save.                                             |
| `children`             | `ReactNode`               |                        | The form.                                                                                                  |

`ChannelEditDetailsContextValue`:

| Value                  | Type                      | Description                                                                                                                           |
| ---------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `store`                | `EditChannelDetailsStore` | The form's state.                                                                                                                     |
| `submit`               | `() => Promise<void>`     | Saves the name and the image, the ones that changed, with `Channel.updatePartial()`. Rejects with an `AggregateError` when one fails. |
| `compressImageQuality` | `number`                  | As passed to the provider.                                                                                                            |
| `doFileUploadRequest`  | `GlobalFileUploadRequest` | As passed to the provider.                                                                                                            |

An empty name unsets the channel's name, and a removed image unsets its image. Each save publishes a success or failure notification.

### EditChannelDetailsStore

The provider creates the store once, from the channel's name and image at that moment, so a `channel.updated` event doesn't overwrite what the user is typing. Mount the provider once for each edit.

| Field           | Type                                    | Description                                                                                        |
| --------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `currentName`   | `string`                                | The name in the field.                                                                             |
| `initialName`   | `string`                                | The channel's name when the form opened, `custom.name`, or `''`.                                   |
| `initialImage`  | `string \| undefined`                   | The channel's image when the form opened, `custom.image`.                                          |
| `updatedImage`  | `File \| null \| undefined`             | `undefined` while untouched, the picked `File`, or `null` once the image is removed.               |
| `pendingAction` | `EditChannelImagePendingAction \| null` | `'camera'`, `'library'` or `'reset'`, picked in the image sheet and run once the sheet has closed. |

`setCurrentName(name)`, `setUpdatedImage(image)` and `setPendingAction(action)` change them. `useIsNameEdited(store)`, `useIsImageEdited(store)` and `useAreChannelDetailsEdited(store)` say whether anything changed, and re-render only when the answer does.

## ChannelAddMembersProvider

`ChannelAddMembersForm` renders it around the add members form, with the form's `searchSource`. It's also a notification target in the `channel-details` panel.

`ChannelAddMembersProviderProps`:

| Prop           | Type               | Default               | Description                                                                                   |
| -------------- | ------------------ | --------------------- | --------------------------------------------------------------------------------------------- |
| `searchSource` | `UserSearchSource` | users, sorted by name | The source of the users to add. It's used as it is, so activate it and set its sort yourself. |
| `children`     | `ReactNode`        |                       | The form.                                                                                     |

The default source loads 25 users a page, searches with `name: { $autocomplete: query }`, and lists every user while the query is empty.

`ChannelAddMembersContextValue`:

| Value            | Type                  | Description                                                                                                       |
| ---------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `searchSource`   | `UserSearchSource`    | The source of the list.                                                                                           |
| `selectionStore` | `SelectionStore`      | The ids of the selected users, in `state.selectedIds`. `select(id)`, `deselect(id)` and `toggle(id)` change them. |
| `submit`         | `() => Promise<void>` | Adds the selected users with `Channel.addMembers({ members })`. Rejects when the request fails.                   |

`useIsSelected(selectionStore, id)` and `useIsSelectionEmpty(selectionStore)` read the selection, and re-render only when their answer changes.

## The list providers

`ChannelMemberListProvider`, `ChannelPinnedMessageListProvider`, `ChannelMediaListProvider` and `ChannelFileAttachmentListProvider` take the same props:

| Prop           | Type                                                 | Default                  | Description                            |
| -------------- | ---------------------------------------------------- | ------------------------ | -------------------------------------- |
| `channel`      | `Channel`                                            | required                 | The channel the default source is for. |
| `searchSource` | `ChannelMemberSearchSource` or `MessageSearchSource` | the default source below | The source to provide instead.         |
| `children`     | `ReactNode`                                          |                          | The list.                              |

Their value is `{ searchSource }`. The provider creates the default source when it mounts, even when you pass your own, and keeps it for as long as it's mounted. A list renders the provider with the list's own `searchSource` prop. The provider builds a new value object each time it renders.

| Provider                            | Default source                                                                                                |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `ChannelMemberListProvider`         | A `ChannelMemberSearchSource` of the channel, sorted by name, searched with `name: { $autocomplete }`         |
| `ChannelPinnedMessageListProvider`  | A `MessageSearchSource` with `cid` of the channel and `pinned: true`, searched with `text: { $q }`            |
| `ChannelMediaListProvider`          | A `MessageSearchSource` with `cid` of the channel and `attachments.type` in `image` and `video`, newest first |
| `ChannelFileAttachmentListProvider` | A `MessageSearchSource` with `cid` of the channel and `attachments.type` of `file` or `audio`, newest first   |

Each loads 25 items a page and allows an empty query. The sources don't follow events. A source shows what the server returned when it last queried.

`MessageSearchSource` and `ChannelMemberSearchSource` come from `stream-chat`. [Search sources](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/search-sources/) explains their filters, sort and paging.

## Example

A photos screen without videos, with a source of your own passed to `MediaList`:

```tsx title="src/ChannelPhotosScreen.tsx"
import { useState } from "react";
import { View } from "react-native";
import { MessageSearchSource } from "stream-chat";
import type { Channel as StreamChannel } from "stream-chat";
import {
  ChannelDetailsContextProvider,
  MediaList,
  useChatContext,
} from "stream-chat-react-native";

export const ChannelPhotosScreen = ({
  channel,
}: {
  channel: StreamChannel;
}) => {
  const { client } = useChatContext();
  const [searchSource] = useState(() => {
    const source = new MessageSearchSource(client, {
      allowEmptySearchString: true,
      pageSize: 25,
      resetOnNewSearchQuery: false,
    });
    source.messageSearchChannelFilters = {
      cid: channel.cid,
      members: undefined,
    };
    source.messageSearchFilters = {
      "attachments.type": "image",
      type: undefined,
    };
    source.messageSearchSort = [{ field: "created_at", direction: -1 }];
    source.activate();
    return source;
  });

  return (
    <ChannelDetailsContextProvider channel={channel}>
      <View style={{ flex: 1 }}>
        <MediaList searchSource={searchSource} />
      </View>
    </ChannelDetailsContextProvider>
  );
};
```

`members: undefined` and `type: undefined` drop the filters `MessageSearchSource` adds by default. The grid still shows only the images and videos of the messages it gets, so a message with an image and a video shows both.

## Related

- [ChannelDetails](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details/): the screen.
- [Channel details lists](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-lists/): the lists and forms that render these providers.
- [Channel details hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/channel-details-hooks/#the-lists-of-channel-details): the hooks that read them.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-contexts/](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-contexts/).