# ComponentsContext

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

`ComponentsContext` holds the override keys: for each replaceable part of the UI, the component the SDK renders there. Set keys with `WithComponents`, and read them with `useComponentsContext()`. [Overriding components](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/) explains how overrides apply, and lists [every key by area of the screen](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#override-keys-by-area). This page covers the provider, the hook and their types.

## Best practices

- Declare the `overrides` object once, at module scope, with its components declared at module scope too. `WithComponents` reads it once, when it mounts.
- Put `WithComponents` above the component that reads the key. `OverlayProvider` reads the image gallery's keys, `MessageOverlayBackground` and `MessageActions`, and `Chat` reads `ChatLoadingIndicator`, so those keys work only from a `WithComponents` around them. See [Where to put WithComponents](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#where-to-put-withcomponents).
- Read a key with `useComponentsContext()` in a component of your own, rather than importing the SDK's default, so it shows the override the app registered.
- A custom message component receives no props. It reads the message with `useMessageContext()`. See [A custom MessageItemView](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#a-custom-messageitemview).

## Basic usage

```tsx title="src/AppOverrides.tsx"
import type { PropsWithChildren } from "react";
import { Text } from "react-native";
import { WithComponents } from "stream-chat-react-native";
import type {
  ComponentOverrides,
  EmptyStateProps,
} from "stream-chat-react-native";

const EmptyState = ({ listType }: EmptyStateProps) => (
  <Text>
    {listType === "channel" ? "No conversations yet" : "Nothing here yet"}
  </Text>
);

// Declared once, at module scope.
const overrides: ComponentOverrides = { EmptyStateIndicator: EmptyState };

export const AppOverrides = ({ children }: PropsWithChildren) => (
  <WithComponents overrides={overrides}>{children}</WithComponents>
);
```

A component of your own renders the same part through the context, so it shows `EmptyState` inside `AppOverrides` and the SDK's default elsewhere:

```tsx title="src/NoResults.tsx"
import { useComponentsContext } from "stream-chat-react-native";

export const NoResults = () => {
  const { EmptyStateIndicator } = useComponentsContext();

  return <EmptyStateIndicator listType="default" />;
};
```

## WithComponents

| Prop        | Type                 | Default  | Description                                                                                                                                                                                        |
| ----------- | -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `overrides` | `ComponentOverrides` | required | The keys to set for everything below. They replace the same keys from a `WithComponents` above, and the other keys keep their outer value. `icons` merges icon by icon. Read once, when it mounts. |

`WithComponents` also renders its `children`. No provider removes the overrides from above; to give a part of the app the SDK's component back, set the key to the default component again.

## useComponentsContext

`useComponentsContext()` returns a `ResolvedComponents` object: every key, with the overrides in effect merged over the SDK's defaults, and `icons` merged icon by icon. It never throws. Outside every `WithComponents`, it returns the defaults.

The object is built once for each component that calls the hook, when it mounts. An override registered later reaches the component only when it mounts again.

## Types

| Type                 | What it is                                                                                                                                                                                                                                                                   |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ComponentOverrides` | The type of `overrides`. Every key is optional. It has 187 keys: 172 that have a default component, 14 [optional slots](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#optional-slots) that have none, and `icons`, a partial map of icon components. |
| `ResolvedComponents` | The type `useComponentsContext()` returns. It types every key as defined, and `icons` as the full map.                                                                                                                                                                       |

>
> **Warning:** `ResolvedComponents` also types the 14 optional slots as defined, but they're `undefined` at runtime until you set them. Check one before rendering it, for example `MessageText ? <MessageText {...props} /> : null`.
>

The keys in the type that no component reads, and so change nothing, are listed in [Keys that change nothing](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/overriding-components/#keys-that-change-nothing).

## Related hooks

- `useComponentsContext()` returns the merged keys, as above.
- `useMessageContext()` gives a custom message component its message. See [MessageContext](https://getstream.io/chat/docs/sdk/react-native/v10/component-reference/message/messagecontext/).
- `useTheme()` gives a custom component the theme, so it matches the SDK's. See [Theming](https://getstream.io/chat/docs/sdk/react-native/v10/ui/customizing/theming/#reading-the-theme-in-your-own-components).

---

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