

# Client-Messaging-SDK für IVS Chat: Bewährte Methoden zu React und React Native
<a name="chat-sdk-react-best-practices"></a>

In diesem Dokument werden die wichtigsten Methoden zur Verwendung des Amazon-IVS-Chat-Messaging-SDK für React und React Native beschrieben. Diese Informationen sollten es Ihnen ermöglichen, typische Chat-Funktionen in einer React-Anwendung zu erstellen, und Ihnen den Hintergrund geben, den Sie benötigen, um tiefer in die fortgeschritteneren Teile des IVS-Chat-Messaging-SDKs einzutauchen.

## Erstellen eines ChatRoom-Initializer-Hooks
<a name="chatroom-initializer-hook"></a>

Die `ChatRoom`-Klasse enthält grundlegende Chat-Methoden und Listener zur Verwaltung des Verbindungsstatus und zum Abhören von Ereignissen wie empfangenen und gelöschten Nachrichten. Hier zeigen wir, wie man Chat-Instances richtig in einem Hook speichert.

### Implementierung
<a name="chatroom-initializer-hook-implementation"></a>

------
#### [ TypeScript ]

```
// useChatRoom.ts

import React from 'react';
import { ChatRoom, ChatRoomConfig } from 'amazon-ivs-chat-messaging';

export const useChatRoom = (config: ChatRoomConfig) => {
  const [room] = React.useState(() => new ChatRoom(config));

  return { room };
};
```

------
#### [ JavaScript ]

```
import React from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';

export const useChatRoom = (config) => {
  const [room] = React.useState(() => new ChatRoom(config));

  return { room };
};
```

------

Hinweis: Wir verwenden nicht die `dispatch`-Methode aus dem `setState`-Hook, da Sie die Konfigurationsparameter nicht im laufenden Betrieb aktualisieren können. Das SDK erstellt einmalig eine Instance und es ist nicht möglich, den Token-Anbieter zu aktualisieren.

**Wichtig**: Verwenden Sie den `ChatRoom`-Initialisierer-Hook einmal, um eine neue Chatroom-Instance zu initialisieren.

### Beispiel
<a name="chatroom-initializer-hook-example"></a>

**TypeScript/JavaScript**:

```
// ...

const MyChatScreen = () => {
  const userId = 'Mike';
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(ROOM_ID, ['SEND_MESSAGE']),
  });

  const handleConnect = () => {
    room.connect();
  };

  // ...
};

// ...
```

### Auf den Verbindungsstatus warten
<a name="chatroom-initializer-hook-connection-state"></a>

Optional können Sie Updates zum Verbindungsstatus in Ihrem Chatroom-Hook abonnieren.

#### Implementierung
<a name="connection-state-implementation"></a>

------
#### [ TypeScript ]

```
// useChatRoom.ts

import React from 'react';
import { ChatRoom, ChatRoomConfig, ConnectionState } from 'amazon-ivs-chat-messaging';

export const useChatRoom = (config: ChatRoomConfig) => {
  const [room] = useState(() => new ChatRoom(config));

  const [state, setState] = React.useState<ConnectionState>('disconnected');

  React.useEffect(() => {
    const unsubscribeOnConnecting = room.addListener('connecting', () => {
      setState('connecting');
    });

    const unsubscribeOnConnected = room.addListener('connect', () => {
      setState('connected');
    });

    const unsubscribeOnDisconnected = room.addListener('disconnect', () => {
      setState('disconnected');
    });

    return () => {
      unsubscribeOnConnecting();
      unsubscribeOnConnected();
      unsubscribeOnDisconnected();
    };
  }, []);

  return { room, state };
};
```

------
#### [ JavaScript ]

```
// useChatRoom.js

import React from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';

export const useChatRoom = (config) => {
  const [room] = useState(() => new ChatRoom(config));

  const [state, setState] = React.useState('disconnected');

  React.useEffect(() => {
    const unsubscribeOnConnecting = room.addListener('connecting', () => {
      setState('connecting');
    });

    const unsubscribeOnConnected = room.addListener('connect', () => {
      setState('connected');
    });

    const unsubscribeOnDisconnected = room.addListener('disconnect', () => {
      setState('disconnected');
    });

    return () => {
      unsubscribeOnConnecting();
      unsubscribeOnConnected();
      unsubscribeOnDisconnected();
    };
  }, []);

  return { room, state };
};
```

------

## Anbieter von ChatRoom-Instances
<a name="chatroom-instance-provider"></a>

Um den Hook in anderen Komponenten zu verwenden (um Prop-Drilling zu vermeiden), können Sie mit React `context` einen Chatroom-Anbieter erstellen.

### Implementierung
<a name="chatroom-instance-provider-implementation"></a>

------
#### [ TypeScript ]

```
// ChatRoomContext.tsx

import React from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';

const ChatRoomContext = React.createContext<ChatRoom | undefined>(undefined);

export const useChatRoomContext = () => {
  const context = React.useContext(ChatRoomContext);

  if (context === undefined) {
    throw new Error('useChatRoomContext must be within ChatRoomProvider');
  }

  return context;
};

export const ChatRoomProvider = ChatRoomContext.Provider;
```

------
#### [ JavaScript ]

```
// ChatRoomContext.jsx

import React from 'react';
import { ChatRoom } from 'amazon-ivs-chat-messaging';

const ChatRoomContext = React.createContext(undefined);

export const useChatRoomContext = () => {
  const context = React.useContext(ChatRoomContext);

  if (context === undefined) {
    throw new Error('useChatRoomContext must be within ChatRoomProvider');
  }

  return context;
};

export const ChatRoomProvider = ChatRoomContext.Provider;
```

------

### Beispiel
<a name="chatroom-instance-provider-example"></a>

Nach der Erstellung von `ChatRoomProvider` können Sie Ihre Instance mit `useChatRoomContext` verwenden.

**Wichtig**: Platzieren Sie den Anbieter nur dann in der Root-Ebene, wenn Sie Zugriff auf die `context`-Verbindung zwischen dem Chat-Bildschirm und den anderen Komponenten in der Mitte benötigen, um unnötiges erneutes Rendern zu vermeiden, wenn Sie nach Verbindungen suchen. Andernfalls stellen Sie den Anbieter so nahe an den Chatbildschirm wie möglich.

**TypeScript/JavaScript**:

```
// AppContainer

const AppContainer = () => {
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(ROOM_ID, ['SEND_MESSAGE']),
  });

  return (
    <ChatRoomProvider value={room}>
      <MyChatScreen />
    </ChatRoomProvider>
  );
};

// MyChatScreen

const MyChatScreen = () => {
  const room = useChatRoomContext();

  const handleConnect = () => {
    room.connect();
  };
  // ...
};

// ...
```

## Erstellen eines Nachrichten-Listeners
<a name="message-listener"></a>

Um über alle eingehenden Nachrichten auf dem Laufenden zu bleiben, sollten Sie die `message`- und `deleteMessage`-Ereignisse abonnieren. Hier ist ein Code, der Chat-Nachrichten für Ihre Komponenten bereitstellt.

**Wichtig**: Aus Leistungs-Gründen trennen wir `ChatMessageContext` von `ChatRoomProvider`, da wir viele Renderings erhalten können, wenn der Chat-Nachrichten-Listener den Status seiner Nachricht aktualisiert. Denken Sie daran, `ChatMessageContext` in den Komponenten zu verwenden, in denen Sie `ChatMessageProvider` verwenden werden.

### Implementierung
<a name="message-listener-implementation"></a>

------
#### [ TypeScript ]

```
// ChatMessagesContext.tsx

import React from 'react';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useChatRoomContext } from './ChatRoomContext';

const ChatMessagesContext = React.createContext<ChatMessage[] | undefined>(undefined);

export const useChatMessagesContext = () => {
  const context = React.useContext(ChatMessagesContext);

  if (context === undefined) {
    throw new Error('useChatMessagesContext must be within ChatMessagesProvider);
  }

  return context;
};

export const ChatMessagesProvider = ({ children }: { children: React.ReactNode }) => {
  const room = useChatRoomContext();

  const [messages, setMessages] = React.useState<ChatMessage[]>([]);

  React.useEffect(() => {
    const unsubscribeOnMessageReceived = room.addListener('message', (message) => {
      setMessages((msgs) => [message, ...msgs]);
    });

    const unsubscribeOnMessageDeleted = room.addListener('messageDelete', (deleteEvent) => {
      setMessages((prev) => prev.filter((message) => message.id !== deleteEvent.messageId));
    });

    return () => {
      unsubscribeOnMessageDeleted();
      unsubscribeOnMessageReceived();
    };
  }, [room]);

  return <ChatMessagesContext.Provider value={messages}>{children}</ChatMessagesContext.Provider>;
};
```

------
#### [ JavaScript ]

```
// ChatMessagesContext.jsx

import React from 'react';
import { useChatRoomContext } from './ChatRoomContext';

const ChatMessagesContext = React.createContext(undefined);

export const useChatMessagesContext = () => {
  const context = React.useContext(ChatMessagesContext);

  if (context === undefined) {
    throw new Error('useChatMessagesContext must be within ChatMessagesProvider);
  }

  return context;
};

export const ChatMessagesProvider = ({ children }) => {
  const room = useChatRoomContext();

  const [messages, setMessages] = React.useState([]);

  React.useEffect(() => {
    const unsubscribeOnMessageReceived = room.addListener('message', (message) => {
      setMessages((msgs) => [message, ...msgs]);
    });

    const unsubscribeOnMessageDeleted = room.addListener('messageDelete', (deleteEvent) => {
      setMessages((prev) => prev.filter((message) => message.id !== deleteEvent.messageId));
    });

    return () => {
      unsubscribeOnMessageDeleted();
      unsubscribeOnMessageReceived();
    };
  }, [room]);

  return <ChatMessagesContext.Provider value={messages}>{children}</ChatMessagesContext.Provider>;
};
```

------

### Beispiel in React
<a name="message-listener-example-react"></a>

**Wichtig**: Denken Sie daran, Ihren Nachrichtencontainer mit `ChatMessagesProvider` zu verpacken. Die `Message`-Zeile ist eine Beispielkomponente, die den Inhalt einer Nachricht anzeigt.

**TypeScript/JavaScript**:

```
// your message list component...

import React from 'react';
import { useChatMessagesContext } from './ChatMessagesContext';

const MessageListContainer = () => {
  const messages = useChatMessagesContext();

  return (
    <React.Fragment>
      {messages.map((message) => (
        <MessageRow message={message} />
      ))}
    </React.Fragment>
  );
};
```

### Beispiel in React Native
<a name="message-listener-example-react-native"></a>

Standardmäßig enthält `ChatMessage` `id`, das automatisch als React Schlüssel in `FlatList` für jede Zeile verwendet wird; Sie müssen daher nicht an `keyExtractor` übergeben.

------
#### [ TypeScript ]

```
// MessageListContainer.tsx

import React from 'react';
import { ListRenderItemInfo, FlatList } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useChatMessagesContext } from './ChatMessagesContext';

const MessageListContainer = () => {
  const messages = useChatMessagesContext();

  const renderItem = useCallback(({ item }: ListRenderItemInfo<ChatMessage>) => <MessageRow />, []);

  return <FlatList data={messages} renderItem={renderItem} />;
};
```

------
#### [ JavaScript ]

```
// MessageListContainer.jsx

import React from 'react';
import { FlatList } from 'react-native';
import { useChatMessagesContext } from './ChatMessagesContext';

const MessageListContainer = () => {
  const messages = useChatMessagesContext();

  const renderItem = useCallback(({ item }) => <MessageRow />, []);

  return <FlatList data={messages} renderItem={renderItem} />;
};
```

------

## Mehrere Chatroom-Instances in einer App
<a name="multiple-chatroom-instances"></a>

Wenn Sie in Ihrer App mehrere Chatrooms gleichzeitig verwenden, schlagen wir vor, jeden Anbieter für jeden Chat zu erstellen und ihn im Chat-Anbieter zu nutzen. In diesem Beispiel erstellen wir einen Hilfe-Bot und einen Kunden-Hilfe-Chat. Wir schaffen einen Anbieter für beide.

------
#### [ TypeScript ]

```
// SupportChatProvider.tsx

import React from 'react';
import { SUPPORT_ROOM_ID, SOCKET_URL } from '../../config';
import { tokenProvider } from '../tokenProvider';
import { ChatRoomProvider } from './ChatRoomContext';
import { useChatRoom } from './useChatRoom';

export const SupportChatProvider = ({ children }: { children: React.ReactNode }) => {
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(SUPPORT_ROOM_ID, ['SEND_MESSAGE']),
  });

  return <ChatRoomProvider value={room}>{children}</ChatRoomProvider>;
};

// SalesChatProvider.tsx

import React from 'react';
import { SALES_ROOM_ID, SOCKET_URL } from '../../config';
import { tokenProvider } from '../tokenProvider';
import { ChatRoomProvider } from './ChatRoomContext';
import { useChatRoom } from './useChatRoom';

export const SalesChatProvider = ({ children }: { children: React.ReactNode }) => {
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(SALES_ROOM_ID, ['SEND_MESSAGE']),
  });

  return <ChatRoomProvider value={room}>{children}</ChatRoomProvider>;
};
```

------
#### [ JavaScript ]

```
// SupportChatProvider.jsx

import React from 'react';
import { SUPPORT_ROOM_ID, SOCKET_URL } from '../../config';
import { tokenProvider } from '../tokenProvider';
import { ChatRoomProvider } from './ChatRoomContext';
import { useChatRoom } from './useChatRoom';

export const SupportChatProvider = ({ children }) => {
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(SUPPORT_ROOM_ID, ['SEND_MESSAGE']),
  });

  return <ChatRoomProvider value={room}>{children}</ChatRoomProvider>;
};

// SalesChatProvider.jsx

import React from 'react';
import { SALES_ROOM_ID, SOCKET_URL } from '../../config';
import { tokenProvider } from '../tokenProvider';
import { ChatRoomProvider } from './ChatRoomContext';
import { useChatRoom } from './useChatRoom';

export const SalesChatProvider = ({ children }) => {
  const { room } = useChatRoom({
    regionOrUrl: SOCKET_URL,
    tokenProvider: () => tokenProvider(SALES_ROOM_ID, ['SEND_MESSAGE']),
  });

  return <ChatRoomProvider value={room}>{children}</ChatRoomProvider>;
};
```

------

### Beispiel in React
<a name="multiple-chatroom-instances-example-react"></a>

Jetzt können Sie verschiedene Chat-Anbieter verwenden, die denselben `ChatRoomProvider` verwenden. Später können Sie denselben `useChatRoomContext` in jedem Bildschirm/jeder Ansicht wiederverwenden.

**TypeScript/JavaScript**:

```
// App.tsx / App.jsx

const App = () => {
  return (
    <Routes>
      <Route
        element={
          <SupportChatProvider>
            <SupportChatScreen />
          </SupportChatProvider>
        }
      />
      <Route
        element={
          <SalesChatProvider>
            <SalesChatScreen />
          </SalesChatProvider>
        }
      />
    </Routes>
  );
};
```

### Beispiel in React Native
<a name="multiple-chatroom-instances-example-react-native"></a>

**TypeScript/JavaScript**:

```
// App.tsx / App.jsx

const App = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="SupportChat">
        <SupportChatProvider>
          <SupportChatScreen />
        </SupportChatProvider>
      </Stack.Screen>
      <Stack.Screen name="SalesChat">
        <SalesChatProvider>
          <SalesChatScreen />
        </SalesChatProvider>
      </Stack.Screen>
    </Stack.Navigator>
  );
};
```

**TypeScript/JavaScript**:

```
// SupportChatScreen.tsx / SupportChatScreen.jsx

// ...

const SupportChatScreen = () => {
  const room = useChatRoomContext();

  const handleConnect = () => {
    room.connect();
  };

  return (
    <>
      <Button title="Connect" onPress={handleConnect} />
      <MessageListContainer />
    </>
  );
};

// SalesChatScreen.tsx / SalesChatScreen.jsx

// ...

const SalesChatScreen = () => {
  const room = useChatRoomContext();

  const handleConnect = () => {
    room.connect();
  };

  return (
    <>
      <Button title="Connect" onPress={handleConnect} />
      <MessageListContainer />
    </>
  );
};
```