# Client

Stream Chat for React Native uses the [Stream Chat client](https://github.com/GetStream/stream-chat-js) to connect to and communicate with the Stream API.

The full [JavaScript client docs](https://getstream.io/chat/docs/javascript/) should be referenced for detailed information on directly using the client.

## Setup

To interact with the Stream Chat API you must create a client instance and connect to the API, usually as an authenticated user.

### Instantiation

The Stream Chat client, `StreamChat` is a dependency of `stream-chat-react-native` and can be imported from `stream-chat`.
To create a client instance you can call `getInstance` on the client and provide and API key.

```ts
import { StreamChat } from "stream-chat";

const client = StreamChat.getInstance("api_key");
```

>
> **Warning:** **Usage of `StreamChat.getInstance()` available since stream-chat@2.12.0.**
>
> <br />
> This new Singleton pattern allows you to instantiate a unique StreamChat client, i.e create a StreamChat instance and
> retrieve it wherever you need it on your app to perform API calls. After calling it once, any following <code>
>   getInstance
> </code> call will return the initial StreamChat instance. This will prevent you from accidentally creating multiple
> StreamChat instances, opening multiple WebSockets, and driving up your concurrent connections unnecessarily.
> <br />
> <br />
>
> Stream Chat is backward compatible. Users can continue using <code>new StreamChat()</code> if desired.
>
> <br />
>
> ```ts
> const client = new StreamChat("api_key");
> ```
>
> Calling <code>new StreamChat()</code> repeatedly will create new copies of the client and in turn new WebSocket connections when <code>connectUser</code> is called.
> If you are using <code>new StreamChat()</code> you need to be vigilant about your use to ensure you are not creating multiple WebSocket connections unnecessarily.
>

### Connecting a User

To connect a user a the `connectUser` function should be called and provided with the user object and `user_token`.
The `user_token` is typically sent from your back end when a user is authenticated.

```ts
await client.connectUser(
  {
    id: "testUser",
    name: "Test User",
  },
  "user_token",
);
```

It is recommended to not repeatedly call `connectUser` unnecessarily, multiple calls to `connectUser` will result in warnings, and attempting to call `connectUser` before disconnecting a current user will throw an Error.

## UI Components

The Stream Chat for React Native UI components handle most interactions with the client for you after connecting with an authenticated user.

### Providing the Client to the UI

To provide the client to the UI components you simply provide the client instance as the prop `client` to the `Chat` component.

```tsx
import { StreamChat } from "stream-chat";
import { Chat } from "stream-chat-react-native";

const client = StreamChat.getInstance("api_key");

export const Screen = () => (
  <Chat client={client}>{/** App components */}</Chat>
);
```

The Stream Chat for React Native UI components then handle interacting with the client internally by accessing the client via [`context`](https://reactjs.org/docs/context.html).

>
> **Note:** If you are customizing certain components or functionality you may have to interact with the client as well.
> You can access the client provided to the `Chat` component internally via the `useChatContext`.
>
> <br />
>
> ```ts
> import { useChatContext } from "stream-chat-react-native";
>
> const { client } = useChatContext();
> ```
>

### Using UI Functions

The UI provides a number of functions that interact with the client while keeping the UI state in sync using `context`.
The [contexts section](https://getstream.io/chat/docs/sdk/react-native/v3/contexts/attachment-picker-context/) details what functions are accessible.
When customizing your application you should ensure you are utilizing the correct functions to keep the UI state up to date.

The `sendMessage` function for instance, provided by `useMessageInputContext`, is not the same as the `sendMessage` function found directly on a `channel` in the client.
Therefore calling `channel.sendMessage(messageData)` will not result in a message optimistically showing in the UI, or a failed send state, instead the message will not show until it is returned by the server.

>
> **Warning:** You should not assume any function directly called on the client will result in a UI update.
> The UI state is managed internally by the components and `context`, most client interactions require an event returned by the server to update the UI.
>

## Accessing the Client Instance

There are multiple ways to access the client instance throughout your application.
[As mentioned](#providing-the-client-to-the-ui) you can access the `client` via `useChatContext` when inside the `Chat` component.
This works well if you can wrap your entire application in a single `Chat` component and have the `StreamChat` instance provided throughout your app via the internal `context`.
But if you have multiple screens that contain `Chat` components where a client instance is necessary you will need to access the shared instance in other ways.

You can store the client in a [`context`](https://reactjs.org/docs/context.html) you create yourself.
Create your own custom class that provides it.
Or using the Singleton structure you can call `getInstance` when required to always be returned the current instance if one exists, or create a new one otherwise.

>
> **Warning:** Do not create and connect multiple instances using `new StreamChat()`, this will result in multiple `StreamChat` instances and opening multiple WebSocket connections.
>

## Direct Interaction

There may be some direct interaction with the client that is required for your application.
Referring to the [full documentation](https://getstream.io/chat/docs/javascript/) is suggested for detailed information on client functionality.
Common interactions with the client used in conjunction with the Stream Chat for React Native components have been included for convenience.

### Creating a Channel

A channel must be initialized with either an `id` or a list of members for the channel.
If you provide a list of members an `id` will be auto-generated on backend for the channel.

>
> **Note:** You can't add or remove members from channel created using a list of members.
>

**Channel Id**

```ts
/**
 *  Channel created using a channel id
 */
const channel = client.channel(channel_type, "channel_id", {
  name: "My New Channel",
});
```

**Members List**

```ts
/**
 *  Channel created using a members list
 */
const channel = client.channel(channel_type, {
    members: ['userOne', 'userTwo']
    name: 'My New Channel',
});
```

To create a channel on the server you must call `create` or `watch` on a new channel instance.
`create` will create the channel while `watch` will both create the channel and subscribe the client to updates on the channel.

**watch**

```ts
await channel.watch();
```

**create**

```ts
await channel.create();
```

### Disconnecting a User

To disconnect a user you can call `disconnect` on the client.

```ts
await client.disconnectUser();
```

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v3/basics/client/](https://getstream.io/chat/docs/sdk/react-native/v3/basics/client/).