Channel List

A ChannelPaginator instance represents a channel list. It automatically reorders the list based on WebSocket events such as message.new.

Initialization

Create a ChannelPaginator, register it with the channel manager, and load the first page. Call registerSubscriptions() once, so lists follow new messages, new channels and membership changes.

const channelPaginator = new ChannelPaginator({
  client,
  filters: { type: "messaging", members: { $in: [userId] } },
  sort: [{ field: "last_message_at", direction: -1 }],
});

client.channelManager.registerSubscriptions();
client.channelManager.insertPaginator({ paginator: channelPaginator });

await channelPaginator.toTail();

Reading

const {
  items: channels,
  isLoading,
  hasMoreTail,
} = channelPaginator.state.getLatestValue();

Subscribe to render changes:

const unsubscribe = channelPaginator.state.subscribeWithSelector(
  ({ items }) => ({ items }),
  ({ items }) => renderChannelList(items),
);

Loading more channels

toTail() loads the next page into items. hasMoreTail tells you whether there are more to load. A page is 10 channels by default; see Configure the query to change it.

const { hasMoreTail } = channelPaginator.state.getLatestValue();

if (hasMoreTail) {
  await channelPaginator.toTail();
}

Configure the query

The options of ChannelPaginator make up its queryChannels request. See Query channels for the filter and sort fields.

  • filters and sort: which channels the list holds, and in what order.
  • requestOptions: the other request fields, such as message_limit, member_limit or presence.
  • paginatorOptions.pageSize: channels per page, 10 by default.
const channelPaginator = new ChannelPaginator({
  client,
  filters: { type: "messaging", members: { $in: [userId] } },
  sort: [{ field: "last_message_at", direction: -1 }],
  requestOptions: { message_limit: 25, member_limit: 10, presence: true },
  paginatorOptions: { pageSize: 20 },
});

To change the query of a list you already have, set its staticFilters, sort or options (the request options) and call reload().

channelPaginator.staticFilters = {
  type: "messaging",
  members: { $in: [userId] },
  archived: true,
};
channelPaginator.sort = [{ field: "created_at", direction: -1 }];

await channelPaginator.reload();

WebSocket events

After client.channelManager.registerSubscriptions(), every registered list follows these events. The channel is checked against each list's filters and sort, then added, moved or removed.

Event Effect on the list
message.new, notification.message_new Moves the channel to its new position. A channel the client hasn't loaded yet is fetched and added.
notification.added_to_channel, channel.visible Adds the channel if it matches the filters.
notification.removed_from_channel, channel.deleted Removes the channel.
channel.hidden, channel.updated, channel.truncated, member.updated, message.deleted (hard delete) Re-checks the channel, for example, a list filtered by hidden drops it.
Read events, notification.channel_mutes_updated Re-checks the channel, only in lists that filter or sort by unread state or muted.

To only update channels that are already loaded, put ignoreEventsForUnknownChannels (exported from stream-chat) first in an event's handlers. addEventHandler returns a function that removes the handler.

const removeHandler = client.channelManager.addEventHandler({
  eventType: "notification.message_new",
  handle: ignoreEventsForUnknownChannels,
  index: 0,
});

// Back to the default behavior
removeHandler();