# 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.

```js label="JavaScript"
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

```js label="JavaScript"
const {
  items: channels,
  isLoading,
  hasMoreTail,
} = channelPaginator.state.getLatestValue();
```

Subscribe to render changes:

```js label="JavaScript"
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](#configure-the-query) to change it.

```js label="JavaScript"
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](https://getstream.io/chat/docs/javascript/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.

```js label="JavaScript"
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()`.

```js label="JavaScript"
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.

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

// Back to the default behavior
removeHandler();
```

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/javascript/state-channel-list/](https://getstream.io/chat/docs/javascript/state-channel-list/).