# Channel

> **Info:** This is release candidate documentation for **Stream Chat React SDK v15**. For the latest stable version, see the [latest version (v14)](https://getstream.io/chat/docs/sdk/react/).

`Channel` binds one channel to the components inside it. It activates the channel while it's mounted, renders the channel's container around its children, and stops the channel's audio players when the channel changes. It doesn't load the channel. [Channel UI](https://getstream.io/chat/docs/sdk/react/v15/ui/components/channel-ui/#the-channel-component) explains what it does, and [Reading state in components](https://getstream.io/chat/docs/sdk/react/v15/ui/reading-state-in-components/) how its children read the channel's state.

## Best practices

- Pass a channel that is already watched, for example with `Channel.watch()`. A channel from a channel list is loaded already, and the SDK's search results watch the channel they open.
- With `ChatView`, let `ChannelSlot` render `Channel` for the channel in its slot. See [Workspace with ChatView](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/).
- Read the channel in its children with `useChannel()`, and its state with `useStateStore`, rather than passing them down as props.
- `Channel` takes no component props. Replace the parts inside it with `WithComponents`, or by rendering different children.
- While no channel is selected, render `ChannelPlaceholder` in its place.

## Basic usage

```tsx
import {
  Channel,
  ChannelHeader,
  MessageComposer,
  MessageList,
} from "stream-chat-react";

export const ChannelPanel = () => (
  <Channel channel={channel}>
    <ChannelHeader />
    <MessageList />
    <MessageComposer />
  </Channel>
);
```

`MessageList` renders `channel.messagePaginator`, and `MessageComposer` writes into `channel.messageComposer`. A component of your own reads the same channel:

```tsx
import type { ChannelStateData } from "stream-chat";
import { useChannel, useStateStore } from "stream-chat-react";

const frozenSelector = ({ data }: ChannelStateData) => ({
  frozen: data?.frozen,
});

export const FrozenBanner = () => {
  const channel = useChannel();
  const { frozen } = useStateStore(channel.state, frozenSelector);

  if (!frozen) return null;

  return <div className="frozen-banner">This channel is read-only.</div>;
};
```

## Props

| Prop      | Type                         | Default  | Description                                                                                                                                                                                                                                |
| --------- | ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `channel` | `Channel` from `stream-chat` | required | The channel to bind. Watch it before you pass it. `Channel` activates it while mounted, so it stays loaded and is reloaded after a reconnect; see [Entity lifecycle](https://getstream.io/chat/docs/sdk/react/v15/state/state-and-entities/entity-lifecycle/). |

`Channel` takes nothing else. The props it took in v14 are listed in [Upgrade to v15](https://getstream.io/chat/docs/sdk/react/v15/release-guides/upgrade-to-v15/#channel-props-that-moved).

`ChannelPlaceholder` takes the props of a `div`. It renders the same container as `Channel`, with the classes `str-chat`, the `theme` classes and `str-chat__channel`, but with no channel bound. Its `className` is added to those classes.

## Examples

### Watch the channel before passing it

```tsx
import { useEffect, useState } from "react";
import type { Channel as StreamChannel } from "stream-chat";
import {
  Channel,
  ChannelHeader,
  MessageComposer,
  MessageList,
  useChatContext,
} from "stream-chat-react";

export const SupportChannel = ({ channelId }: { channelId: string }) => {
  const { client } = useChatContext();
  const [channel, setChannel] = useState<StreamChannel>();

  useEffect(() => {
    let cancelled = false;

    client
      .channel("messaging", channelId)
      .watch()
      .then((watchedChannel) => {
        if (!cancelled) setChannel(watchedChannel);
      })
      .catch((error) => console.error("Could not watch the channel", error));

    return () => {
      cancelled = true;
    };
  }, [channelId, client]);

  if (!channel) return <div>Loading the channel...</div>;

  return (
    <Channel channel={channel}>
      <ChannelHeader />
      <MessageList />
      <MessageComposer />
    </Channel>
  );
};
```

`Channel.watch()` resolves with the channel instance to use from then on. Loading and error states are yours to render: `Channel` has no query to report on.

### Render something while no channel is selected

```tsx
import type { Channel as StreamChannel } from "stream-chat";
import {
  Channel,
  ChannelHeader,
  ChannelPlaceholder,
  MessageComposer,
  MessageList,
} from "stream-chat-react";

export const ChannelArea = ({ channel }: { channel?: StreamChannel }) => {
  if (!channel) {
    return (
      <ChannelPlaceholder>Pick a channel to start chatting.</ChannelPlaceholder>
    );
  }

  return (
    <Channel channel={channel}>
      <ChannelHeader />
      <MessageList />
      <MessageComposer />
    </Channel>
  );
};
```

## Related hooks

| Hook                             | Returns                                                                                             |
| -------------------------------- | --------------------------------------------------------------------------------------------------- |
| `useChannel()`                   | the channel: the thread's channel inside a `Thread`, otherwise the `Channel`'s. Throws outside both |
| `useChannelInstanceContext()`    | `{ channel }` inside a `Channel`, `{}` outside                                                      |
| `useMessageComposerController()` | the composer of the channel, or of the thread inside a `Thread`                                     |
| `useStateStore(store, selector)` | a selection of a store, such as `channel.state`, that re-renders the component when it changes      |

[Reading state in components](https://getstream.io/chat/docs/sdk/react/v15/ui/reading-state-in-components/#which-owner-a-hook-reads) explains which owner each hook reads, and [Channel and thread hooks](https://getstream.io/chat/docs/sdk/react/v15/reference/hooks/channel-and-thread-hooks/) lists the hooks for channel state.

---

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