# How components connect to state

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

Components in the UI layer don't fetch or keep chat data. They read it from objects in the state layer, and three components hand those objects down the tree: `Chat` gives the client, `Channel` gives a channel, and `Thread` gives a thread. Every component inside reads from the nearest one.

Take these two screens:

```tsx
import type {
  Channel as StreamChannel,
  Thread as StreamThread,
} from "stream-chat";
import {
  Channel,
  MessageComposer,
  MessageList,
  Thread,
} from "stream-chat-react-native";

export const ChannelScreen = ({ channel }: { channel: StreamChannel }) => (
  <Channel channel={channel}>
    <MessageList />
    <MessageComposer />
  </Channel>
);

export const ThreadScreen = ({ thread }: { thread: StreamThread }) => (
  <Thread thread={thread}>
    <MessageList />
    <MessageComposer />
  </Thread>
);
```

The two `MessageList`s are the same component. The first renders `channel.messagePaginator`, because the nearest owner is the channel. The second renders `thread.messagePaginator`, with the parent message above the replies, because the nearest owner is the thread. The two `MessageComposer`s work the same way: the first writes into `channel.messageComposer`, the second into `thread.messageComposer`. No prop says which one to use.

## OverlayProvider and Chat

`OverlayProvider` goes around your screens, above `Chat`. It hosts what the SDK draws over everything else: the message menu that opens on a long press, and the image gallery. A screen presented in a separate native window, such as a native modal on iOS, needs its own `OverlayProvider`; see [Chat in modals](https://getstream.io/chat/docs/sdk/react-native/v10/ui/layout/chat-in-modals/).

`Chat` goes around every other SDK component. It takes a connected client, such as the one `useCreateChatClient` returns (see [Quick start](https://getstream.io/chat/docs/sdk/react-native/v10/getting-started/quick-start/#create-the-client)).

It provides:

- the client, through `ChatContext`, with `getAppSettings()` for the app's settings and `isMessageAIGenerated`;
- translations, through `TranslationContext`, from the `i18nInstance` you pass or a default English one;
- the theme, through `ThemeContext`, from the `style` you pass merged over the default theme.

While it's mounted, it also:

- starts the event subscriptions of `client.threads`, `client.polls` and `client.reminders`, and the reminders' timers, so the thread list, polls and reminders follow events. It stops them when it unmounts. Each `ChannelList` starts the subscriptions of `client.channelManager` while it's mounted.
- reports the device's network state to the client, and closes the WebSocket while the app is in the background and opens it again in the foreground, unless `closeConnectionOnBackground` is `false`. See [Connection](https://getstream.io/chat/docs/sdk/react-native/v10/state/connection/).
- with `enableOfflineSupport`, opens the local database for the connected user, and renders `ChatLoadingIndicator` until it's ready. See [Offline support](https://getstream.io/chat/docs/sdk/react-native/v10/state/offline-support/offline-support/).

`Chat` doesn't connect the user, load channels or decide which screen shows what.

## Channel and Thread

`Channel` binds one channel to the components inside it. It takes a `channel`, and configuration props for the message list, the messages and the composer below it:

- **It loads the channel.** When it mounts, it watches the channel unless the channel is already watched and loaded with its latest messages, so a channel from a channel list opens without a request. Set `initializeOnMount={false}` to watch it yourself.
- **It sets the page size** of the channel's message list to 25 messages, unless you set one in `client.config` (see [Message paginators](https://getstream.io/chat/docs/sdk/react-native/v10/state/loading-data/message-paginators/)).
- **It activates the channel while it's mounted.** An active channel stays loaded and is reloaded after a reconnect. See [Entity lifecycle](https://getstream.io/chat/docs/sdk/react-native/v10/state/state-and-entities/entity-lifecycle/).
- **It marks the channel read** when it opens with unread messages, unless `markReadOnMount` is `false`, and again after a reconnect when the list shows the latest messages.
- **It follows a superseded channel.** When the channel you pass is replaced by another object for the same conversation, `Channel` renders the replacement (see [Superseded channels](https://getstream.io/chat/docs/sdk/react-native/v10/state/state-and-entities/entity-lifecycle/#superseded-channels)).

`Thread` binds one thread. It takes a `thread`, and the same configuration props as `Channel`:

- **Get the thread from the client,** from `onThreadSelect` on `MessageList` and `ThreadList`, or with `client.threads.ensure({ channel, parentMessage })`. Don't construct one with `new Thread()`. When the client already holds a thread for that parent message, a second instance stays unmanaged and receives no events.
- **It loads the thread.** It loads the first page of replies when none are loaded, and reloads the thread while its state is stale.
- **It activates the thread while it's mounted.** An active thread marks new replies read as they arrive, and is reloaded after a reconnect.
- **It doesn't need a `Channel` around it.** Render it on its own screen. Inside a `Thread`, `useChannel()` returns the thread's channel.
- **It takes its own configuration.** Props set on a `Channel` don't reach a `Thread`, so pass the same ones, such as `keyboardVerticalOffset`, `supportedReactions` or `messageActions`, to both.

Which object each part of a channel or thread holds is on [What channels and threads hold](https://getstream.io/chat/docs/sdk/react-native/v10/state/channels-and-threads/what-channels-and-threads-hold/).

## Contexts

Your own components read the same objects through context hooks. This one sits inside a `Channel` or a `Thread`:

```tsx
import { Text } from "react-native";
import {
  useChannel,
  useChatContext,
  useThreadContext,
} from "stream-chat-react-native";

export const WhereAmI = () => {
  const { client } = useChatContext();
  const channel = useChannel();
  const { thread } = useThreadContext();

  return (
    <Text>
      {client.userId} is in {channel.cid}
      {thread ? `, in the thread of message ${thread.id}` : ""}
    </Text>
  );
};
```

| Hook                      | Gives                                                                                 | Provided by                                             | Outside its provider            |
| ------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------- |
| `useChatContext()`        | `client`, `getAppSettings`, `isMessageAIGenerated`                                    | `Chat`                                                  | throws                          |
| `useChannel()`            | the channel: the thread's channel inside a `Thread`, otherwise the `Channel`'s        | `Channel` or `Thread`                                   | throws                          |
| `useChannelContext()`     | `channel` and the channel's display options                                           | `Channel` or `Thread`                                   | throws                          |
| `useThreadContext()`      | `{ thread, allowThreadMessagesInChannel }`                                            | `Thread`                                                | returns `{ thread: undefined }` |
| `useMessagePaginator()`   | the message list's paginator: the thread's inside a `Thread`, otherwise the channel's | `Channel` or `Thread`                                   | throws                          |
| `useMessageContext()`     | the message, its handlers and display options for one message                         | `Message`, once for each message a message list renders | returns `{}`                    |
| `useTranslationContext()` | `t`, `tDateTimeParser`, `userLanguage`                                                | `Chat` and `OverlayProvider`                            | throws                          |

`useMessageContext()` is how a custom message component reads its message. See [Overriding components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/).

The objects these hooks return hold their data in stores. Rendering from a store, and the rules that keep it current, are on [Reading state in components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/reading-state-in-components/).

## Pitfalls

- **Wrapping `Thread` in a `Channel`.** It doesn't need one. Render it on its own screen, or next to `Channel` on the same screen.
- **Setting props on `Channel` only.** A `Thread` doesn't inherit them. Pass the same configuration props to both.
- **Reading the channel from your own state inside a thread.** Read it with `useChannel()` and the thread with `useThreadContext()`, so the component works in both places.
- **Creating a thread with `new Thread`.** Use `client.threads.ensure()`, so the thread is the one instance the client keeps up to date.

Used in: every page that renders state, including [Channel UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/channel-ui/), [Thread UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/thread-ui/) and [Message list UI](https://getstream.io/chat/docs/sdk/react-native/v10/ui/components/message-list-ui/).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/ui/how-components-connect-to-state/](https://getstream.io/chat/docs/sdk/react-native/v10/ui/how-components-connect-to-state/).