# State and entity hooks

> **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/).

These hooks give a component the client, the channel or the thread it renders in, and a way to read any store. They're exported from `stream-chat-react-native` and `stream-chat-expo`.

How to use them, the `useStateStore` rules and the pitfalls are on [Reading state in components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/reading-state-in-components/). What a store is, and which objects have one, is on [Reactive state](https://getstream.io/chat/docs/sdk/react-native/v10/state/state-and-entities/reactive-state/).

Each entry gives the signature, then:

- **Returns:** what the hook gives back.
- **Reads:** the store or the context it reads.
- **Re-renders:** what makes the component render again.
- **Needs:** where the component must sit, and what the hook does outside that place.

## useStateStore

Subscribes to one store and returns the part of its value that a selector picks.

```ts
import type { StateStore } from "@stream-io/state-store";

type Selection = Readonly<Record<string, unknown> | Readonly<unknown[]>>;

declare function useStateStore<
  T extends Record<string, unknown>,
  O extends Selection,
>(store: StateStore<T>, selector: (state: T) => O): O;

declare function useStateStore<
  T extends Record<string, unknown>,
  O extends Selection,
>(store: StateStore<T> | undefined, selector: (state: T) => O): O | undefined;
```

- **Returns:** what the selector returns, an object or a tuple. `undefined` when `store` is `undefined`, so a component can pass `thread?.state`.
- **Reads:** the store you pass. `StateStore` is the store type from `@stream-io/state-store`.
- **Re-renders:** when a value in the selection changes. The hook compares each key of the previous selection with `===`. A different `store` or `selector` makes it subscribe again, so define selectors at module scope.
- **Needs:** nothing. It works outside `Chat`.

The unread thread count has no hook of its own. Read it from `client.threads.state`:

```tsx
import { Text } from "react-native";
import type { ThreadManagerState } from "stream-chat";
import { useChatContext, useStateStore } from "stream-chat-react-native";

const unreadSelector = (state: ThreadManagerState) => ({
  unreadThreadCount: state.unreadThreadCount,
});

export const UnreadThreadsBadge = () => {
  const { client } = useChatContext();
  const { unreadThreadCount } = useStateStore(
    client.threads.state,
    unreadSelector,
  );

  if (!unreadThreadCount) return null;
  return <Text>{unreadThreadCount}</Text>;
};
```

## useChatContext

Returns what `Chat` provides.

```ts
useChatContext(): ChatContextValue
```

- **Returns:**
  - `client`: the client passed to `Chat`.
  - `getAppSettings()`: resolves to the app settings. The first call for a user requests them, and later calls reuse the result. A failed request isn't kept, so the next call requests again. With offline support, a successful request is stored in the offline database, and a failed one falls back to the stored copy. `Chat` makes the first call itself once a user is connected.
  - `isMessageAIGenerated`: the `Chat` prop of the same name. It returns `false` for every message by default.
- **Reads:** React context. It subscribes to no store, so reading a getter such as `client.user` from it doesn't re-render the component when the value changes.
- **Re-renders:** when `Chat` gets another `client` or another `isMessageAIGenerated` function. `getAppSettings` keeps its identity. Pass `isMessageAIGenerated` from module scope, or every render of `Chat` re-renders every component that reads the context.
- **Needs:** `Chat`. Throws outside it.

The context is on [ChatContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/chat/chatcontext/).

## useCreateChatClient

Creates a client and connects a user.

```ts
useCreateChatClient(params: {
  apiKey: string;
  tokenOrProvider: TokenOrProvider;
  userData: ClientUser;
  options?: DeepPartial<InstanceConfigTree>;
}): StreamChat | null
```

The params:

- `apiKey`: your Stream API key.
- `tokenOrProvider`: the user's token, or a function that returns one.
- `userData`: the user to connect, as `client.connectUser()` takes it. Only `id` is required.
- `options`: the configuration tree, the same one `client.config.set()` takes. The hook reads it on the first render only. Unless it sets `client.networkConnection.statusReporter` itself, the hook adds `netInfoStatusReporter`, so the network status is known from the start. `Chat` keeps a reporter set here.

- **Returns:** `null` until `client.connectUser()` resolves, and then the client. Each client is a new `StreamChat`, not the shared instance of `StreamChat.getInstance()`.
- **Reads:** no store and no context.
- **Re-renders:** when the client connects, and when it's replaced. A new `apiKey`, a new `tokenOrProvider` or a `userData` with another `id` disconnects the user, returns `null`, and connects a new client. Other changes to `userData` are ignored. Define a token provider at module scope or with `useCallback`, or every render creates a new client.
- **Needs:** nothing. Call it above `Chat`, and pass the client to `Chat` once it isn't `null`.

When the component unmounts, the hook waits for the connection to finish, then disconnects the user. If `client.connectUser()` rejects, for example on a cold start without a network, the hook keeps returning `null`. To open the app on locally stored data with offline support, create the client yourself, as [Offline support](https://getstream.io/chat/docs/sdk/react-native/v10/state/offline-support/offline-support/) shows. [Quick start](https://getstream.io/chat/docs/sdk/react-native/v10/getting-started/quick-start/) uses the hook.

## useChannel

Returns the channel the component renders in.

```ts
useChannel(): Channel
```

- **Returns:** inside a `Thread`, the thread's channel. Otherwise the channel of the nearest `Channel`.
- **Reads:** the `Thread` and `Channel` contexts. No store.
- **Re-renders:** when the `Thread` or the `Channel` above switches to another thread or channel, or the channel is frozen or unfrozen. Other changes to the channel's state don't re-render it: read them with `useStateStore(channel.state, selector)`.
- **Needs:** a `Channel` or a `Thread`. Throws outside both.

Inside a `Thread`, `channel.messagePaginator` and `channel.messageComposer` are the channel's, not the thread's. [The right owner inside threads](https://getstream.io/chat/docs/sdk/react-native/v10/ui/reading-state-in-components/#the-right-owner-inside-threads) says which to read instead. The channel's state 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/).

## useChannelContext

Returns the channel and the display settings of the nearest `Channel` or `Thread`.

```ts
useChannelContext(): ChannelContextValue
```

- **Returns:**
  - `channel`: the channel. Inside a `Thread`, the thread's channel.
  - `disabled`: whether the channel is frozen.
  - `enforceUniqueReaction`, `enableMessageGroupingByUser`, `maxTimeBetweenGroupedMessages`, `hideDateSeparators`, `hideStickyDateHeader` and `allowDateSeparatorForSystemMessages`: the props of the same names on `Channel` or `Thread`.
- **Reads:** the context `Channel` and `Thread` provide. No store.
- **Re-renders:** when the channel instance changes, or the channel is frozen or unfrozen. A change to one of the display props after mount doesn't provide a new value.
- **Needs:** a `Channel` or a `Thread`. Throws outside both.

`useChannel()` returns the same channel. Use `useChannelContext()` when you also need the settings. The context is on [ChannelContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel/channelcontext/).

## useThreadContext

Returns the thread the component renders in.

```ts
useThreadContext(): ThreadContextValue
```

- **Returns:** `{ thread, allowThreadMessagesInChannel }`. `thread` is the `Thread`'s thread, and `allowThreadMessagesInChannel` its prop of that name, `true` by default. Outside a `Thread`, `{ thread: undefined, allowThreadMessagesInChannel: false }`.
- **Reads:** the context `Thread` provides. No store.
- **Re-renders:** when the `Thread` above switches to another thread, or its `allowThreadMessagesInChannel` prop changes.
- **Needs:** nothing. Never throws, so a component can tell whether it renders in a thread.

The SDK has no hook for a thread's state. Read `thread.state` with `useStateStore`. Its fields are on [What channels and threads hold](https://getstream.io/chat/docs/sdk/react-native/v10/state/channels-and-threads/what-channels-and-threads-hold/#thread) and [Thread and thread manager](https://getstream.io/chat/docs/sdk/react-native/v10/reference/state/thread-and-thread-manager/).

```tsx
import { Text } from "react-native";
import type { ThreadState } from "stream-chat";
import { useStateStore, useThreadContext } from "stream-chat-react-native";

const replyCountSelector = (state: ThreadState) => ({
  replyCount: state.replyCount,
});

export const ReplyCount = () => {
  const { thread } = useThreadContext();
  const { replyCount } = useStateStore(thread?.state, replyCountSelector) ?? {};

  if (replyCount === undefined) return null;
  return <Text>{replyCount} replies</Text>;
};
```

## useThreadListItemContext

Returns what the `ThreadList` row being rendered shows.

```ts
useThreadListItemContext(): ThreadListItemContextValue
```

- **Returns:**
  - `thread`: the row's thread, and `channel`, its channel.
  - `parentMessage`: the thread's parent message.
  - `lastReply`: the newest reply, from `thread.messagePaginator.aggregateState`.
  - `ownUnreadMessageCount`: the current user's unread replies.
  - `draftMessage`: what the user has typed in the thread's composer, or `undefined` when it's empty.
  - `dateString`: the time of the newest reply, formatted with the `timestamp.ThreadListItem` translation key. `deletedAtDateString`: the time the thread was deleted, formatted the same way, or `undefined`.
- **Reads:** the context `ThreadListItem` sets for its row. `ThreadListItem` subscribes to `thread.state`, the paginator's `aggregateState` and the composer's stores, and builds the value from them.
- **Re-renders:** whenever `ThreadListItem` renders, since it passes a new value each time. It renders when one of those stores changes.
- **Needs:** a `ThreadListItem`, which `ThreadList` renders for each thread. Outside one it returns an empty object, typed as the full value, so check `thread` before you use it.

Use it in a component you pass to `WithComponents` as `ThreadListItem`, as [Replies and threads](https://getstream.io/chat/docs/sdk/react-native/v10/features/messaging/replies-and-threads/#replacing-a-thread-list-row) shows.

## useMutedUsers

Returns the users the current user has muted.

```ts
useMutedUsers(): UserMuteResponse[]
```

- **Returns:** the user mutes, each with the muted user as `target`. `[]` before they load.
- **Reads:** `client.mutedUsersStore`, field `mutedUsers`. The client fills it when the user connects, and replaces it on `notification.mutes_updated`.
- **Re-renders:** when the list of mutes changes.
- **Needs:** `Chat`. Throws outside it.

## useMutedChannels

Returns the channels the current user has muted.

```ts
useMutedChannels(): ChannelMute[]
```

- **Returns:** `client.mutedChannels`, the channel mutes.
- **Reads:** `client.mutedChannels`, a plain field rather than a store. The hook reads it again when the `health.check` event or the `notification.channel_mutes_updated` event arrives. The client also replaces it on `connection.ok`, which the hook doesn't listen for, so the mutes of a new connection show on the next `health.check`.
- **Re-renders:** when one of those events replaces the list.
- **Needs:** `Chat`. Throws outside it.

Whether one channel is muted is also in its own state: `useIsChannelMuted(channel)` on [Channel preview hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/channel-preview-hooks/#useischannelmuted) reads it.

## Stores without a hook

Read these stores with `useStateStore` and your own selector:

| To read                                 | Store and field                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Blocked user IDs                        | `client.blockedUsers`, `userIds`                                                                                   |
| The unread thread count, unseen threads | `client.threads.state`, `unreadThreadCount` and `unseenThreadIds`                                                  |
| A channel's settings in effect          | `channel.configState`                                                                                              |
| A composer's settings in effect         | `messageComposer.configState`                                                                                      |
| A thread's state                        | `thread.state`, with the thread from `useThreadContext()`                                                          |
| A poll's state                          | `poll.state`, with the poll from [`usePollContext()`](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/poll-hooks/) |

The settings stores are explained on [Configuration](https://getstream.io/chat/docs/sdk/react-native/v10/state/state-and-entities/configuration/). The connected user, `client.user`, has no store: read it when you need it, or listen for the [events](https://getstream.io/chat/docs/sdk/react-native/v10/state/state-and-entities/events/) that change it.

## Other exported hooks

### Context hooks of components

Each component that provides a context exports a hook for it. The values are listed with the component:

| Hook                                                            | Provided by                        | Reference                                                                                                                 |
| --------------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `useOverlayContext`                                             | `OverlayProvider`                  | [OverlayContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/chat/overlaycontext/)                                |
| `useComponentsContext`                                          | `WithComponents`, and the defaults | [ComponentsContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel/componentscontext/)                       |
| `useOwnCapabilitiesContext`                                     | `Channel` and `Thread`             | [OwnCapabilitiesContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel/owncapabilitiescontext/)             |
| `useMessagesContext`                                            | `Channel` and `Thread`             | [MessagesContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-list/messagescontext/)                      |
| `useMessageContext`                                             | `Message`                          | [MessageContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/messagecontext/)                             |
| `useMessageInputContext`                                        | `Channel` and `Thread`             | [MessageInputContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-composer/messageinputcontext/)          |
| `useChannelsContext`                                            | `ChannelList`                      | [ChannelsContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-list/channelscontext/)                      |
| `useThreadsContext`                                             | `ThreadList`                       | [ThreadList](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/thread-list/threadlist/)                                 |
| `usePollContext`                                                | `Poll`                             | [Poll components](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/poll-components/)                                   |
| `useChannelDetailsContext` and the context hooks of its screens | `ChannelDetails`                   | [Channel details contexts](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/channel-details/channel-details-contexts/) |
| `useImageGalleryContext`                                        | `OverlayProvider`                  | [Image gallery](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/utilities/image-gallery/)                             |
| `useAttachmentPickerContext`                                    | `Channel` and `Thread`             | [Attachment picker](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message-composer/attachment-picker/)              |
| `useTheme`                                                      | `OverlayProvider` and `Chat`       | [Theming](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/theming/)                                                        |
| `useTranslationContext`                                         | `Chat` and `OverlayProvider`       | [Localization](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/localization/)                                              |

The hooks of the composer, the message, polls, notifications and channel details are on their own pages in this section.

### Hooks that belong to a feature

- **Audio playback:** `useAudioPlayer`, `useActiveAudioPlayer` and `useAudioPlayerContext`. See [Voice recordings and audio playback](https://getstream.io/chat/docs/sdk/react-native/v10/features/rich-content/voice-recordings-and-audio-playback/).
- **The message menu:** `useHasActiveId`, which returns `true` while the menu of a message is open. See [OverlayContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/chat/overlaycontext/).
- **Bottom sheets:** `useBottomSheetContext`, which the content of a `BottomSheetModal` calls to `close()` the sheet with its animation, or to `dismiss()` it before another native modal opens. See [Overlays and bottom sheets](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overlays-and-bottom-sheets/#bottom-sheets).
- **The image gallery:** `useImageGalleryVideoPlayer`. See [Image gallery](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/utilities/image-gallery/).
- **Accessibility:** `useAccessibilityContext`, `useA11yLabel`, `useAccessibilityActivateAction`, `useAccessibilityAnnouncer`, `useAccessibilityServiceEnabled`, `useAnnounceOnShow`, `useAnnounceOnStateChange`, `useIncomingMessageAnnouncements`, `useReducedMotionPreference`, `useResolvedModalAccessibilityProps`, `useScreenReaderEnabled`, `useScreenReaderMountFocus` and `useSetAccessibilityFocus`. See [Accessibility](https://getstream.io/chat/docs/sdk/react-native/v10/features/app-experience/accessibility/).
- **The keyboard:** `useKeyboardContext` and `useAfterKeyboardOpenCallback`. See [Keyboard and insets](https://getstream.io/chat/docs/sdk/react-native/v10/ui/layout/keyboard-and-insets/#the-keyboard-in-your-own-components).
- **Translations:** `useStreami18n`, which `Chat` calls to start a `Streami18n` instance. See [Localization](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/localization/).

### Utilities

These hooks don't read chat state. The SDK's components use them, and they're exported for components of your own:

| Hook                                                | What it does                                                                                                                                                                                                |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useStableCallback(callback)`                       | Returns a function that keeps its identity and always calls the latest `callback`.                                                                                                                          |
| `useViewport(rounded?)`                             | Returns `{ vh, vw }`, which convert a percentage of the window's height or width to points. Updates when the window resizes.                                                                                |
| `useScreenDimensions(rounded?)`                     | The same as `useViewport`, measured against the screen instead of the window. It's deprecated, because the two differ in split view and on foldables. Use `useViewport`.                                    |
| `useScreenOrientation()`                            | Returns `'landscape'` while the window is wider than it is tall, `'portrait'` otherwise.                                                                                                                    |
| `useAppStateListener(onForeground?, onBackground?)` | Calls `onBackground` when the app goes to the background, and `onForeground` when it becomes active again. The `inactive` state calls neither.                                                              |
| `useIsSvg(uri)`                                     | Returns whether `uri` points to an SVG, by its `.svg` extension or an `image/svg+xml` data URI.                                                                                                             |
| `useLoadingImage()`                                 | Returns `{ isLoadingImage, isLoadingImageError, setLoadingImage, setLoadingImageError, onReloadImage }` for an image component, and reloads a failed image when the device comes back online. Needs `Chat`. |

### Hooks left out of this reference

The rest of the exported hooks are the SDK's own plumbing. They're exported so the default components can be rebuilt from parts, but they change with the components that use them:

- The `useCreate*Context` hooks (`useCreateChatContext`, `useCreateChannelContext`, `useCreateMessagesContext`, `useCreateMessageContext`, `useCreateThreadContext`, `useCreateMessageInputContext`, `useCreateInputMessageInputContext`) build the values the providers pass down. Read the contexts with their `use*Context` hooks instead.
- The message overlay and portal hooks (`useOverlayController`, `useIsOverlayActive`, `useIsOverlayClosing`, `useIsTopOverlayHostLayer`, `useShouldTeleportToClosingPortal`, `useClosingPortalHostBlacklist`, `useClosingPortalHostBlacklistState`, `useClosingPortalLayouts`, `usePortalSettledCallback`, `useWithPortalKeyboardSafety`, `useMessageOverlayRuntimeContext`, `useMessageOverlayTargetContext`) drive the message context menu. [Overlays and bottom sheets](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overlays-and-bottom-sheets/) explains what you can change there.
- `useRAFCoalescedValue`, `useMessageList`, `useMicPositionContext` and `useChatConfigContext` serve the message list, the voice recorder and image resizing.
- `useInAppNotificationsState` is deprecated. It reads a store of its own, which no SDK component shows. Use the notification hooks on [Notification hooks](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/notification-hooks/), which read `client.notifications`. `openInAppNotification(notification)` becomes `addNotification({ message, origin, options })` from `useNotificationApi()`, `closeInAppNotification(id)` becomes `removeNotification(id)`, and `notifications` becomes `useNotifications()`. `NotificationList` can replace a list of your own that rendered them, as [Displaying notifications](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/displaying-notifications/) shows.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/state-and-entity-hooks/](https://getstream.io/chat/docs/sdk/react-native/v10/reference/hooks/state-and-entity-hooks/).