# Channel details hooks

> **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/).

These hooks build the channel details screen and the screens it opens: the profile, the navigation rows, the members, the actions, the media, file and pinned message lists, the edit form and the add members form. `ChannelDetails` uses them, and they're exported for screens of your own. They're exported from `stream-chat-react-native` and `stream-chat-expo`.

The screen and its parts are on [Channel details](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details/), its lists on [Channel details lists](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-lists/), and its contexts on [Channel details contexts](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-contexts/). The feature is on [Channel details and members](https://getstream.io/chat/docs/sdk/react-native/v10/features/channels/channel-details-and-members/).

Each entry gives the signature, then:

- **Returns:** what the hook gives back.
- **Reads:** the store or the context it reads.
- **Re-renders:** what makes the component render again.
- **Needs:** where the component must sit, and what the hook does outside that place.

## useChannelDetailsContext

Returns the channel the details screens show.

```ts
useChannelDetailsContext(): ChannelDetailsContextValue
```

- **Returns:**
  - `channel`: the channel passed to `ChannelDetailsContextProvider`.
  - `closeModals()`: closes the screens channel details opened on top of itself, such as the full member list. Call it before you navigate away.
  - `signalStore`: the store `closeModals()` signals through, which those screens listen to.
- **Reads:** the context of `ChannelDetailsContextProvider`. No store.
- **Re-renders:** when the provider gets another channel.
- **Needs:** a `ChannelDetailsContextProvider`, which you render around `ChannelDetails`. Throws outside it.

## useChannelDetailsActionItems

Returns the actions the channel details screen lists.

```ts
useChannelDetailsActionItems(params?: {
  getChannelActionItems?: GetChannelActionItems;
  onChannelDismiss?: () => void;
}): ChannelActionItem[]
```

- **Returns:** the channel action items for the `details` surface, from `useChannelActionItems`, after `getChannelActionItems` changed them. The items with the ID `leave`, `deleteChannel` or `block` also call `onChannelDismiss` after they succeed, so the app can leave a screen whose channel is gone.
- **Reads:** the channel from `useChannelDetailsContext()`, its membership, mute state and the blocked users, as `useChannelActionItems` does.
- **Re-renders:** when one of the items changes, such as after the channel is muted or pinned.
- **Needs:** `Chat` and a `ChannelDetailsContextProvider`. Throws outside them.

In a direct chat, the `block` item becomes "Unblock User" once the user is blocked, and keeps the `block` ID, so a successful unblock calls `onChannelDismiss` too. [In channel details](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/actions/#in-channel-details) explains the items.

## useChannelDetailsNavigationItems

Returns the rows of the navigation section: pinned messages, photos and videos, and files.

```ts
useChannelDetailsNavigationItems(params?: {
  getNavigationItems?: GetChannelDetailsNavigationItems;
}): ChannelDetailsNavigationItem[]
```

- **Returns:** one `{ section, label, Icon, onPress? }` for each row. The default rows are `pinned-messages`, `photos-and-videos` and `files`, with translated labels and the icons of `ComponentsContext`. `getNavigationItems({ context, defaultItems })` returns the rows to render instead: add, remove or reorder rows, or set `onPress` to route a row elsewhere. A row without `onPress` opens the SDK's screen for its section.
- **Reads:** `ComponentsContext` and the translation context. No store.
- **Re-renders:** when `getNavigationItems`, the icons or the language change. Define `getNavigationItems` at module scope.
- **Needs:** `Chat`. Throws outside it.

## useChannelDetailsMemberStatusText

Returns the status line under the channel's title.

```ts
useChannelDetailsMemberStatusText(channel: Channel): string
```

- **Returns:** in a direct chat, "Online" while the other member is online, and `''` otherwise. In a group, "5 members, 2 online", from the `channelDetails.presence.membersOnline.label` key.
- **Reads:** `channel.state`, fields `members`, `memberCount` and `watcherCount`.
- **Re-renders:** when one of those fields changes, presence changes included.
- **Needs:** `Chat`. Throws outside it.

The online count is the channel's watcher count, as in `useChannelOnlineMemberCount`.

## useChannelDetailsMembersPreview

Returns the first members of a channel, for a section that shows a few and links to the rest.

```ts
useChannelDetailsMembersPreview(channel: Channel, max?: number): {
  hasMore: boolean;
  total: number;
  visible: ChannelMemberResponse[];
}
```

- **Returns:**
  - `visible`: the first `max` loaded members, 5 by default.
  - `total`: the member count, or the number of loaded members when the count is `0`.
  - `hasMore`: whether `total` is above `max`.
- **Reads:** `channel.state`, fields `members` and `memberCount`.
- **Re-renders:** when the members or the count change.
- **Needs:** nothing.

## useMemberRoles

Returns the role badges of a member row.

```ts
useMemberRoles(member: ChannelMemberResponse, getMemberRoles?: GetMemberRoles): RoleLabel[]
```

- **Returns:** the roles, each `{ key, label }`, in this order:
  - `owner`, when the member created the channel;
  - `admin`, when the user's app role is `admin`;
  - `moderator`, when the member's `channel_role` is `channel_moderator`.

  `getMemberRoles({ channel, defaultRoleLabels, member, t })` returns the roles instead, `[]` for none.

- **Reads:** the channel from `useChannelDetailsContext()`, and the translation context. No store.
- **Re-renders:** never by itself.
- **Needs:** `Chat` and a `ChannelDetailsContextProvider`. Throws outside them.

## useChannelMemberActionItems

Returns the actions offered for one member.

```ts
useChannelMemberActionItems(params: {
  channel: Channel;
  member: ChannelMemberResponse;
  getChannelMemberActionItems?: GetChannelMemberActionItems;
}): ChannelMemberActionItem[]
```

- **Returns:** the member's action items, after `getChannelMemberActionItems` changed them. For another member, the items mute or unmute, and block or unblock, the user. With the `update-channel-members` capability, an item also removes the member from the channel. Blocking and removing ask for confirmation first. The current user's own row has no items.
- **Reads:** `channel.state` (`ownCapabilities`), `client.mutedUsersStore` and `client.blockedUsers`.
- **Re-renders:** when the capabilities change, and when the member is muted, unmuted, blocked or unblocked.
- **Needs:** `Chat`. Throws outside it.

[Member actions](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/actions/#member-actions) explains the items and builds a member sheet on them.

## useUserActions

Returns the actions that act on one user.

```ts
useUserActions(user: UserResponse | undefined): UserActions
```

- **Returns:** `{ muteUser, unmuteUser, blockUser, unblockUser }`. Each takes `{ onSuccess?, onFailure? }`, publishes a success or failure notification, and does nothing without a user.
- **Reads:** no store.
- **Re-renders:** never by itself. The functions keep their identity.
- **Needs:** `Chat`. Throws outside it.

The handlers never call `onFailure`. A failed `unblockUser` publishes the "Failed to block user" notification, with the type `api:user:block:failed`.

## useUserActivityStatus

Returns a user's presence as text.

```ts
useUserActivityStatus(user?: UserResponse): string
```

- **Returns:** "Online" while the user is online. Otherwise the time they were last active, formatted with the `timestamp.UserActivityStatus` translation key, such as "Last seen 10 minutes ago". "Offline" when the user has no `last_active`.
- **Reads:** the user's `online` and `last_active`, and the translation context. No store.
- **Re-renders:** never by itself. It follows the `user` you pass.
- **Needs:** `Chat`. Throws outside it.

## useEditChannelImage

Returns the functions that take or pick a new channel image.

```ts
useEditChannelImage(): {
  pickImageFromNativePicker: () => Promise<File | undefined>;
  takePhoto: () => Promise<File | undefined>;
}
```

- **Returns:**
  - `takePhoto()`: opens the camera and resolves to the photo.
  - `pickImageFromNativePicker()`: opens the native image picker for one image and resolves to it.

  Both compress the image with `compressImageQuality` from the edit context, and resolve to `undefined` when the user cancels. When access is denied, they show an alert that offers to open the settings, and resolve to `undefined`. Neither uploads the image: `submit()` of the edit context does.

- **Reads:** `compressImageQuality` from `useChannelEditDetailsContext()`.
- **Re-renders:** never by itself.
- **Needs:** `Chat` and a `ChannelEditDetailsProvider`. Throws outside them.

## useMediaList

Turns messages into one tile per image or video attachment.

```ts
useMediaList(messages?: MessageResponse[]): { attachment: Attachment; message: MessageResponse }[]
```

- **Returns:** a tile for each image or video attachment of the messages, in message order. Link previews are left out.
- **Reads:** its argument only.
- **Re-renders:** never by itself.
- **Needs:** nothing.

The media screen passes it the items of its search source.

## useFileAttachmentListSections

Groups the file attachments of messages by month.

```ts
useFileAttachmentListSections(messages?: MessageResponse[]): {
  data: { attachment: Attachment; message: MessageResponse }[];
  title: string;
}[]
```

- **Returns:** sections in message order, each titled with the month of its messages, formatted with the `timestamp.FileAttachmentListSection` translation key. A section holds one tile for each file or audio attachment. Link previews are left out.
- **Reads:** its argument, and the translation context.
- **Re-renders:** when the language changes.
- **Needs:** `Chat`. Throws outside it.

## The lists of channel details

Each list screen provides its search source through a context. Read the results from the source's `state` with `useStateStore`: `items`, `isLoading`, `hasNext`, `searchQuery` and `lastQueryError`.

| Hook                                    | Returns                                                                                                                                                                                             | Provided by                                               |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| `useChannelMemberListContext()`         | `{ searchSource }`: a `ChannelMemberSearchSource` of the channel's members, sorted by name                                                                                                          | `ChannelMemberList`, `ChannelMemberListProvider`          |
| `useChannelMediaListContext()`          | `{ searchSource }`: a `MessageSearchSource` of the channel's messages with images or videos, newest first                                                                                           | `MediaList`, `ChannelMediaListProvider`                   |
| `useChannelFileAttachmentListContext()` | `{ searchSource }`: a `MessageSearchSource` of the channel's messages with files or audio, newest first                                                                                             | `FileAttachmentList`, `ChannelFileAttachmentListProvider` |
| `useChannelPinnedMessageListContext()`  | `{ searchSource }`: a `MessageSearchSource` of the channel's pinned messages                                                                                                                        | `PinnedMessageList`, `ChannelPinnedMessageListProvider`   |
| `useChannelAddMembersContext()`         | `{ searchSource, selectionStore, submit }`: a `UserSearchSource` sorted by name, the selected user IDs, and `submit()`, which adds the selected users and rejects when the request fails            | `ChannelAddMembersForm`, `ChannelAddMembersProvider`      |
| `useChannelEditDetailsContext()`        | `{ store, submit, compressImageQuality, doFileUploadRequest }`: the form's store, and `submit()`, which saves the edited name and image and rejects with an `AggregateError` when one of them fails | `ChannelEditDetailsForm`, `ChannelEditDetailsProvider`    |

Each throws outside its provider. The list providers pass a new value each time they render. Each provider except `ChannelEditDetailsProvider` takes a `searchSource` prop of your own, which replaces the default source with its filters.

The forms keep their state in two stores, with a hook for each question:

| Hook                                  | Returns                                                                                |
| ------------------------------------- | -------------------------------------------------------------------------------------- |
| `useIsSelected(selectionStore, id)`   | whether the user with that ID is selected in the add members form                      |
| `useIsSelectionEmpty(selectionStore)` | whether no user is selected                                                            |
| `useIsNameEdited(store)`              | whether the name in the edit form differs from the channel's name when the form opened |
| `useIsImageEdited(store)`             | whether the image was picked or removed                                                |
| `useAreChannelDetailsEdited(store)`   | whether either was                                                                     |

Each re-renders only when its answer changes. The edit store takes the channel's name and image when the form opens, so a `channel.updated` event doesn't overwrite what the user is typing.

## Example

A header of your own for the channel details screen:

```tsx
import { Text, View } from "react-native";
import {
  useChannelDetailsContext,
  useChannelDetailsMemberStatusText,
  useChannelPreviewDisplayName,
} from "stream-chat-react-native";

export const DetailsHeader = () => {
  const { channel } = useChannelDetailsContext();
  const title = useChannelPreviewDisplayName(channel);
  const status = useChannelDetailsMemberStatusText(channel);

  return (
    <View style={{ alignItems: "center", padding: 16 }}>
      <Text accessibilityRole="header">{title}</Text>
      {status ? <Text>{status}</Text> : null}
    </View>
  );
};
```

Pass it to `WithComponents` as `ChannelDetailsProfile`. Whether the current user may edit the channel or add members is on [Channel and thread hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/channel-and-thread-hooks/#usecaneditchannel): `useCanEditChannel` and `useCanAddMembersToChannel`.

---

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