Info:
This is release candidate documentation for Stream Chat React Native SDK v10. For the latest stable version, see the latest version (v9).

Channel details hooks

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, its lists on Channel details lists, and its contexts on Channel details contexts. The feature is on 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.

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.

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 explains the items.

useChannelDetailsNavigationItems

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

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.

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.

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.

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.

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 explains the items and builds a member sheet on them.

useUserActions

Returns the actions that act on one user.

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.

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.

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.

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.

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:

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: useCanEditChannel and useCanAddMembersToChannel.