# How the SDK is built

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

The SDK has two layers. This page follows one action through both of them: a user opens a channel and sends a message. It ends with the rule that follows from it: which layer to change for what.

## The two layers

- **State** lives in `stream-chat`. Channels, threads, channel lists, message lists and message composers are objects, and each keeps its data in stores that anything can subscribe to. You configure these objects through `client.config`. None of this depends on React.
- **UI** lives in `stream-chat-react`. Its components subscribe to those stores with `useStateStore`, render what they hold, and call methods on the objects when the user acts. You replace any component through `WithComponents`.

The UI has an optional part, the layout: `stream-chat-react/slot-layout`, with `ChatView` at its root. It decides where a channel or a thread opens. Without it, the app renders `Channel` and `Thread` where it wants them.

## One action through the layers

The user has the app from the [Quick start](https://getstream.io/chat/docs/sdk/react/v15/getting-started/quick-start/#add-a-channel-list-with-chatview) open: a channel list, and a `ChatView` with a `channel` slot. They open "Design" and send "Hello". Step through what happens in each layer:

**1. Load**

![ChannelPaginator loads the channels from the Stream API and feeds them to ChannelList](https://getstream.io/docs-assets/images/96e9c08da70d.png)

`ChannelPaginator` loads the channels from the Stream API with a channel query, and feeds them to `ChannelList`: the list subscribes to `paginator.state` and renders a row for each channel. The paginator is registered on `client.channelManager`, which keeps it up to date as events arrive.

**2. Open**

![Opening Design puts the channel in the slot; messagePaginator fills MessageList and messageComposer sets up MessageComposer](https://getstream.io/docs-assets/images/aa6c3472a860.png)

Clicking "Design" calls `openChannel(channel)` from `useWorkspaceNavigation()`. `ChatView` puts the channel in the `channel` slot, and `ChannelSlot` renders a `Channel` for it. Inside it, `MessageList` subscribes to `channel.messagePaginator` and renders its messages, and `MessageComposer` renders from `channel.messageComposer`. Without a layout, the app renders `Channel` itself, as in [Show one channel](https://getstream.io/chat/docs/sdk/react/v15/getting-started/quick-start/#show-one-channel).

**3. Type**

![Typing writes the text into messageComposer, and MessageComposer renders it back](https://getstream.io/docs-assets/images/1ded749473f6.png)

Typing in `MessageComposer` writes the text into `channel.messageComposer`, and the composer UI renders the composer's state back.

**4. Send**

![MessageComposer.send() adds the message locally and sends the request to the Stream API](https://getstream.io/docs-assets/images/7473be0097a8.png)

Pressing Enter calls `MessageComposer.send()`, which hands the message to `channel.messageOperations`. Two paths follow. The local one (blue) adds the message to `messagePaginator` at once, marked as sending, so `MessageList` shows it right away. The other (orange) sends the request to the Stream API, through `channel.requestHandlers.sendMessageRequest` in `client.config` if you set one. The composer is cleared.

**5. Response**

![The server's copy replaces the local message in messagePaginator, and MessageList shows it as sent](https://getstream.io/docs-assets/images/1e3553813968.png)

The API answers with its copy of the message. `messageOperations` stores it in `messagePaginator` in place of the local one, marked as received, and `MessageList` re-renders it as sent. If the request fails, the message is marked failed instead.

**6. Event**

![message.new reaches messagePaginator and the ChannelPaginator, and ChannelList moves Design to the top](https://getstream.io/docs-assets/images/decbb5676d73.png)

The API also sends `message.new` to every client watching the channel, this one included. The channel ingests the message into `messagePaginator`, where it's already present, so nothing changes there, and your own message doesn't count as unread. The channel manager re-inserts "Design" into its paginators, which sort by last message, so it moves to the top and `ChannelList` re-renders in that order.

The UI rendered and placed things; the state layer loaded the data, sent the message and updated the stores. In a thread, the same steps run on `thread.messagePaginator`, `thread.messageComposer` and `thread.messageOperations`, and the send still goes through the channel's request handler.

## The rule

**Change behaviour in the state layer. Change appearance and placement in the UI layer.**

- **Behaviour** is what the objects do: what they load, what they send and what they allow. Change it through `client.config`: configuration values, request handlers, and setup functions that add composer middleware. The change applies wherever the object is used: in the SDK's components, in your own components, and in channels and threads alike.
- **Appearance** is what a component renders. Replace the component through `WithComponents`, or change the CSS variables.
- **Placement** is where a channel or a thread opens. Declare the slots in `ChatView`'s `layouts`, and render them with `ChannelSlot`, `ThreadSlot`, or `Slot` with `slotRenderers`.

Two examples:

- **Turning on [drafts](https://getstream.io/chat/docs/sdk/react/v15/features/messaging/drafts/)** is behaviour: set `messageComposer.drafts.enabled` in `client.config`. It reaches every message composer, in channels and threads, including a composer UI of your own, because it configures the composer objects, not a component.
- **Changing the date separator** is appearance: pass a `DateSeparator` override to `WithComponents`. Every message list below it renders yours.

## Where each layer is taught

- **State.** The State section explains how the objects hold data, load it, keep it current and change it. Start with [Reactive state](https://getstream.io/chat/docs/sdk/react/v15/state/state-and-entities/reactive-state/). [Channel list paginators](https://getstream.io/chat/docs/sdk/react/v15/state/loading-data/channel-list-paginators/) cover channel lists, and [Message composer](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/message-composer/) and [Message operations](https://getstream.io/chat/docs/sdk/react/v15/state/writing-messages/message-operations/) cover writing and sending. [Configuration](https://getstream.io/chat/docs/sdk/react/v15/state/state-and-entities/configuration/) covers `client.config`.
- **UI.** The UI section explains [how components read state](https://getstream.io/chat/docs/sdk/react/v15/ui/how-components-connect-to-state/) and how to change any of them, for example through [Theming](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/theming/), [Localization](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/localization/) and [Actions](https://getstream.io/chat/docs/sdk/react/v15/ui/customizing/actions/). The props of every component are in the Component reference, starting with [Chat](https://getstream.io/chat/docs/sdk/react/v15/component-reference/chat/chat/).
- **Layout.** The UI section's Layout pages, starting with [Workspace with ChatView](https://getstream.io/chat/docs/sdk/react/v15/ui/layout/workspace-with-chatview/), explain where channels and threads open and how users move between them. The APIs are in the Component reference: [Slot layout](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/slot-layout/), [ChatView components](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/chatview-components/) and [Workspace navigation API](https://getstream.io/chat/docs/sdk/react/v15/component-reference/layout/workspace-navigation-api/).

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react/v15/getting-started/how-the-sdk-is-built/](https://getstream.io/chat/docs/sdk/react/v15/getting-started/how-the-sdk-is-built/).