# ChannelListContext

The context value is provided by `ChannelListContextProvider`, which wraps the content rendered by [`ChannelList`](/chat/docs/sdk/react/v13/components/core-components/channel_list/). It exposes API used by the default and custom components. Components that can consume `ChannelListContext` are customizable via `ChannelListProps`:

- `Avatar` - component used to display channel image
- `ChannelSearch` - renders channel search input and results
- `EmptyStateIndicator` - rendered when the channels query returns an empty array
- `LoadingErrorIndicator` - rendered when the channels query fails
- `LoadingIndicator`- rendered during the channels query
- `List` - component rendering `LoadingErrorIndicator`, `LoadingIndicator`, `EmptyStateIndicator`, `Paginator` and the list of channel `Preview` components
- `Paginator` - takes care of requesting to load more channels into the list (pagination)
- `Preview` - renders the information of a channel in the channel list

## Best Practices

- Read from context instead of passing channel list state down manually.
- Defer `setChannels` until the initial query completes to avoid overwrites.
- Keep custom list components aligned with the default loading/error states.
- Use `Paginator` for infinite scroll instead of DIY pagination.
- Gate expensive logic to avoid blocking list rendering.

## Basic Usage

Access the API from `ChannelListContext` with our custom hook:

```tsx
import { useChannelListContext } from "stream-chat-react";

export const CustomComponent = () => {
  const { channels, setChannels } = useChannelListContext();
  // component logic ...
  return {
    /* rendered elements */
  };
};
```

## Values

### channels

State representing the array of loaded channels. By default, the channels query is executed by [`ChannelList`](/chat/docs/sdk/react/v13/components/core-components/channel_list/).

| Type        |
| ----------- |
| `Channel[]` |

### setChannels

Sets the list of channels rendered by `ChannelList`. Be careful when calling this early: the initial `ChannelList` query overwrites the whole [`channels` state](#channels). A common pattern is to wait for the `channels.queried` event before calling `setChannels`.

The example below sets the active channel from the URL. It waits for the first page, then falls back to `getChannel()` if the channel isn’t in that page:

```tsx
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { ChannelList, ChannelListMessenger, ChannelListMessengerProps, getChannel, useChannelListContext, useChatContext } from 'stream-chat-react';

const DEFAULT_CHANNEL_ID = 'general';
const DEFAULT_CHANNEL_TYPE = 'messaging';

const List = (props: ChannelListMessengerProps) => {
  const { channelId } = useParams();
  const navigate = useNavigate();
  const { client, channel, setActiveChannel } = useChatContext();
  const { setChannels } = useChannelListContext();

  useEffect(() => {
    if (!channelId) return navigate(`/${DEFAULT_CHANNEL_ID}`);

    if (channel?.id === channelId || !client) return;

    let subscription: { unsubscribe: () => void } | undefined;
    if(!channel?.id || channel?.id !== channelId) {
      subscription = client.on('channels.queried', (event: Event) => {
        const loadedChannelData = event.queriedChannels?.channels.find((response) => response.channel.id === channelId);

        if (loadedChannelData) {
          setActiveChannel(client.channel( DEFAULT_CHANNEL_TYPE, channelId));
          subscription?.unsubscribe();
          return;
        }

        return getChannel({client, id: channelId, type: DEFAULT_CHANNEL_TYPE}).then((newActiveChannel) => {
          setActiveChannel(newActiveChannel);
          setChannels((channels) => {
            return ([newActiveChannel, ...channels.filter((ch) => ch.data?.cid !== newActiveChannel.data?.cid)]);
          });
        });
      });
    }

    return () => {
      subscription?.unsubscribe();
    };
  }, [channel?.id, channelId, setChannels, client, navigate, setActiveChannel]);

  return <ChannelListMessenger {...props}/>;
};

const Sidebar = () => {
  return (
    // ...
      <ChannelList
        {/* some props   */}
        {/* setting active channel will be performed inside the custom List component */}
        setActiveChannelOnMount={false}
        List={List}
        {/* some props   */}
      />
    // ...
}
```

| Type                                  |
| ------------------------------------- |
| `Dispatch<SetStateAction<Channel[]>>` |


---

This page was last updated at 2026-04-21T09:53:40.732Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v13/components/contexts/channel_list_context/](https://getstream.io/chat/docs/sdk/react/v13/components/contexts/channel_list_context/).