

# SDK per la messaggistica per client di Chat IVS - Tutorial per JavaScript, parte 2: messaggi ed eventi
<a name="chat-sdk-react-tutorial-messages-events"></a>

Questa seconda e ultima parte del tutorial è suddivisa in diverse sezioni:

1. [Sottoscrizione a eventi di messaggi di chat](#chat-react-messages-events-subscribe)

1. [Visualizzazione dei messaggi ricevuti](#chat-react-messages-events-show)

   1.  [Creazione di un componente di messaggio](#chat-react-messages-create-component)

   1. [Riconoscimento dei messaggi inviati dall'utente corrente](#chat-react-messages-recognize)

   1. [Rendering di un elenco di messaggi di chat](#chat-react-messages-render-list)

1. [Esecuzione di azioni in una chat room](#chat-react-messages-events-room-actions)

   1. [Invio di un messaggio](#chat-react-room-actions-sending-message)

   1. [Eliminazione di un messaggio](#chat-react-room-actions-deleting-message)

1. [Fasi successive](#chat-react-messages-events-next-steps)

**Nota**: in alcuni casi, gli esempi di codice per JavaScript e TypeScript sono identici, quindi vengono combinati.

## Prerequisito
<a name="chat-react-messages-events-prerequisite"></a>

Assicurati di aver completato la prima parte di questo tutorial, [Chat room](chat-sdk-react-tutorial-chat-rooms.md).

## Sottoscrizione a eventi di messaggi di chat
<a name="chat-react-messages-events-subscribe"></a>

L'istanza `ChatRoom` utilizza gli eventi per comunicare quando si verificano eventi in una chat room. Per iniziare a implementare l'esperienza di chat, devi mostrare ai tuoi utenti quando altri inviano un messaggio nella stanza a cui sono connessi.

Da qui, puoi effettuare la sottoscrizione a eventi di messaggistica della chat Successivamente, ti mostreremo come aggiornare un elenco di messaggi da te creato che viene aggiornato con ogni messaggio/evento.

Nell'`App`, all'interno dell'hook `useEffect`, sottoscrivi tutti gli eventi di messaggistica:

**TypeScript/JavaScript**:

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

useEffect(() => {
  // ...
  const unsubscribeOnMessageReceived = room.addListener('message', (message) => {});

  return () => {
    // ...
    unsubscribeOnMessageReceived();
  };
}, []);
```

## Visualizzazione dei messaggi ricevuti
<a name="chat-react-messages-events-show"></a>

La ricezione di messaggi è una parte fondamentale dell'esperienza di chat. Utilizzando l'SDK JS Chat, puoi configurare il tuo codice per ricevere facilmente eventi da altri utenti connessi a una chat room.

Successivamente, ti mostreremo come eseguire azioni in una chat room sfruttando i componenti qui creati.

Nella tua `App`, definisci uno stato denominato `messages` con un tipo di array `ChatMessage` denominato `messages`:

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

```
// App.tsx

// ...

import { ChatRoom, ChatMessage, ConnectionState } from 'amazon-ivs-chat-messaging';

export default function App() {
  const [messages, setMessages] = useState<ChatMessage[]>([]);

  //...
}
```

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

```
// App.jsx

// ...

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

export default function App() {
  const [messages, setMessages] = useState([]);

  //...
}
```

------

Successivamente, nella funzione dell'ascoltatore `message`, aggiungi `message` all'array `messages`:

**TypeScript/JavaScript**:

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

// ...

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

// ...
```

Di seguito esaminiamo le attività da completare per mostrare i messaggi ricevuti:

1.  [Creazione di un componente di messaggio](#chat-react-messages-create-component)

1. [Riconoscimento dei messaggi inviati dall'utente corrente](#chat-react-messages-recognize)

1. [Rendering di un elenco di messaggi di chat](#chat-react-messages-render-list)

### Creazione di un componente di messaggio
<a name="chat-react-messages-create-component"></a>

Il componente `Message` è responsabile della visualizzazione del contenuto di un messaggio ricevuto dalla chat room. In questa sezione, crei un componente di messaggi per il rendering di singoli messaggi di chat nell'`App`.

Crea un nuovo file nella directory `src` e chiamalo `Message`. Inserisci il tipo `ChatMessage` di questo componente e passa la stringa `content` dalle proprietà `ChatMessage` per visualizzare il testo del messaggio ricevuto dagli ascoltatori dei messaggi della chat room. Nella struttura di navigazione del progetto, passa a `Message`.

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

```
// Message.tsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';

type Props = {
  message: ChatMessage;
}

export const Message = ({ message }: Props) => {
  return (
    <View style={styles.root}>
      <Text>{message.sender.userId}</Text>
      <Text style={styles.textContent}>{message.content}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
});
```

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

```
// Message.jsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

export const Message = ({ message }) => {
  return (
    <View style={styles.root}>
      <Text>{message.sender.userId}</Text>
      <Text style={styles.textContent}>{message.content}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
});
```

------

**Suggerimento**: utilizza questo componente per archiviare diverse proprietà da rappresentare nelle righe dei messaggi, ad esempio URL di avatar, nomi utente e timestamp del momento in cui è stato inviato il messaggio.

### Riconoscimento dei messaggi inviati dall'utente corrente
<a name="chat-react-messages-recognize"></a>

Per riconoscere il messaggio inviato dall'utente corrente, modifichiamo il codice e creiamo un contesto React per memorizzare l'`userId` dell'utente corrente.

Crea un nuovo file nella directory `src` e chiamalo `UserContext`:

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

```
// UserContext.tsx

import React from 'react';

const UserContext = React.createContext<string | undefined>(undefined);

export const useUserContext = () => {
  const context = React.useContext(UserContext);

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

  return context;
};

export const UserProvider = UserContext.Provider;
```

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

```
// UserContext.jsx

import React from 'react';

const UserContext = React.createContext(undefined);

export const useUserContext = () => {
  const context = React.useContext(UserContext);

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

  return context;
};

export const UserProvider = UserContext.Provider;
```

------

Nota: qui abbiamo usato l'hook `useState` per memorizzare il valore `userId`. In futuro potrai utilizzare `setUserId` per modificare il contesto dell'utente o per scopi di accesso.

Sostituisci, quindi, `userId` nel primo parametro passato a `tokenProvider` utilizzando il contesto creato in precedenza. Assicurati di aggiungere la funzionalità `SEND_MESSAGE` al tuo provider di token, come specificato di seguito, in quanto è necessaria per l'invio di messaggi:

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

```
// App.tsx

// ...

import { useUserContext } from './UserContext';

// ...


export default function App() {
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const userId = useUserContext();
  const [room] = useState(
    () =>
      new ChatRoom({
        regionOrUrl: process.env.REGION,
        tokenProvider: () => tokenProvider(userId, ['SEND_MESSAGE']),
      }),
  );

  // ...
}
```

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

```
// App.jsx

// ...

import { useUserContext } from './UserContext';

// ...


export default function App() {
  const [messages, setMessages] = useState([]);
  const userId = useUserContext();
  const [room] = useState(
    () =>
      new ChatRoom({
        regionOrUrl: process.env.REGION,
        tokenProvider: () => tokenProvider(userId, ['SEND_MESSAGE']),
      }),
  );

  // ...
}
```

------

Nel tuo componente `Message`, usa la variabile `UserContext` creata in precedenza, dichiara la variabile `isMine`, associa `userId` del mittente con `userId` del contesto e applica diversi stili di messaggi per l'utente corrente.

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

```
// Message.tsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useUserContext } from './UserContext';

type Props = {
  message: ChatMessage;
}

export const Message = ({ message }: Props) => {
  const userId = useUserContext();

  const isMine = message.sender.userId === userId;

  return (
    <View style={[styles.root, isMine && styles.mine]}>
      {!isMine && <Text>{message.sender.userId}</Text>}
      <Text style={styles.textContent}>{message.content}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
  mine: {
    flexDirection: 'row-reverse',
    backgroundColor: 'lightblue',
  },
});
```

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

```
// Message.jsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useUserContext } from './UserContext';

export const Message = ({ message }) => {
  const userId = useUserContext();

  const isMine = message.sender.userId === userId;

  return (
    <View style={[styles.root, isMine && styles.mine]}>
      {!isMine && <Text>{message.sender.userId}</Text>}
      <Text style={styles.textContent}>{message.content}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
  mine: {
    flexDirection: 'row-reverse',
    backgroundColor: 'lightblue',
  },
});
```

------

### Rendering di un elenco di messaggi di chat
<a name="chat-react-messages-render-list"></a>

A questo punto, elenca i messaggi utilizzando il componente `FlatList` e `Message`:

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

```
// App.tsx

// ...

const renderItem = useCallback<ListRenderItem<ChatMessage>>(({ item }) => {
  return (
    <Message key={item.id} message={item} />
  );
}, []);

return (
  <SafeAreaView style={styles.root}>
    <Text>Connection State: {connectionState}</Text>
    <FlatList inverted data={messages} renderItem={renderItem} />
    <View style={styles.messageBar}>
      <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
      <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
    </View>
  </SafeAreaView>
);

// ...
```

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

```
// App.jsx

// ...

const renderItem = useCallback(({ item }) => {
  return (
    <Message key={item.id} message={item} />
  );
}, []);

return (
  <SafeAreaView style={styles.root}>
    <Text>Connection State: {connectionState}</Text>
    <FlatList inverted data={messages} renderItem={renderItem} />
    <View style={styles.messageBar}>
      <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
      <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
    </View>
  </SafeAreaView>
);

// ...
```

------

Ora tutti i pezzi del puzzle per l'`App` sono a posto e puoi iniziare a renderizzare i messaggi ricevuti dalla chat room. Continua di seguito per scoprire come eseguire azioni in una chat room sfruttando i componenti appena creati.

## Esecuzione di azioni in una chat room
<a name="chat-react-messages-events-room-actions"></a>

L'invio di messaggi e l'esecuzione delle azioni dei moderatori sono alcune delle principali modalità di interazione con una chatroom. Qui imparerai come utilizzare vari oggetti di richiesta chat per eseguire azioni comuni in Chatterbox, ad esempio l'invio di un messaggio, l'eliminazione di un messaggio e la disconnessione di altri utenti.

Tutte le azioni in una chat room seguono uno schema comune: per ogni azione eseguita in una chat room, esiste un oggetto di richiesta corrispondente. Per ogni richiesta è presente un oggetto di risposta corrispondente che si riceve alla conferma della richiesta.

Se ai tuoi utenti sono offerte le funzionalità corrette quando crei un token di chat, possono eseguire correttamente le azioni corrispondenti utilizzando gli oggetti della richiesta per vedere quali richieste puoi eseguire in una chatroom.

Di seguito, spieghiamo come [inviare un messaggio](#chat-react-room-actions-sending-message) ed [eliminare un messaggio](#chat-react-room-actions-deleting-message).

### Invio di un messaggio
<a name="chat-react-room-actions-sending-message"></a>

La classe `SendMessageRequest` consente l'invio di messaggi in una chat room. Qui puoi modificare la tua `App` per inviare una richiesta di messaggio utilizzando il componente che hai creato in [Creazione dell'input di un messaggio](chat-sdk-react-tutorial-chat-rooms.md#chat-react-rooms-message-input) (nella parte 1 di questo tutorial).

Per iniziare, definisci una nuova proprietà booleana denominata `isSending` con l'hook `useState`. Usa questa nuova proprietà per attivare lo stato disabilitato dell'elemento `button` usando la costante `isSendDisabled`. Nel gestore eventi per il tuo `SendButton`, cancella il valore per `messageToSend` e imposta `isSending` su true.

*Poiché effettuerai una chiamata API da questo pulsante, l'aggiunta della proprietà booleana `isSending` consente di evitare che si verifichino più chiamate API contemporaneamente, disabilitando le interazioni utente con il `SendButton` fino al completamento della richiesta.*

Nota: l'invio di messaggi funziona solo se hai aggiunto la funzionalità `SEND_MESSAGE` al tuo provider di token, come descritto sopra in [Riconoscimento dei messaggi inviati dall'utente corrente](#chat-react-messages-recognize).

**TypeScript/JavaScript**:

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

// ...

const [isSending, setIsSending] = useState(false);

// ...

const onMessageSend = () => {
  setIsSending(true);
  setMessageToSend('');
};

// ...

const isSendDisabled = connectionState !== 'connected' || isSending;

// ...
```

Prepara la richiesta creando una nuova istanza `SendMessageRequest` passando il contenuto del messaggio al costruttore. Dopo aver impostato gli stati `isSending` e `messageToSend`, chiama il metodo `sendMessage`, che invia la richiesta alla chat room. Infine, deseleziona il flag `isSending` quando ricevi la conferma o il rifiuto della richiesta.

**TypeScript/JavaScript**:

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

// ...
import { ChatRoom, ConnectionState, SendMessageRequest } from 'amazon-ivs-chat-messaging'
// ...

const onMessageSend = async () => {
  const request = new SendMessageRequest(messageToSend);
  setIsSending(true);
  setMessageToSend('');

  try {
    const response = await room.sendMessage(request);
  } catch (e) {
    console.log(e);
    // handle the chat error here...
  } finally {
    setIsSending(false);
  }
};

// ...
```

Dai una chance a Chatterbox: prova a inviare un messaggio creandone una bozza con `MessageBar` e toccando quindi `SendButton`. Dovresti vedere il messaggio inviato renderizzato all'interno del `MessageList` creato in precedenza.

### Eliminazione di un messaggio
<a name="chat-react-room-actions-deleting-message"></a>

Per eliminare un messaggio da una chat room, è necessario disporre delle funzionalità adeguate. Le funzionalità vengono concesse durante l'inizializzazione del token di chat utilizzato per l'autenticazione in una chat room. Ai fini di questa sezione, `ServerApp` della sezione [Configurazione di un server di autenticazione/autorizzazione locale](chat-sdk-react-tutorial-chat-rooms.md#chat-react-rooms-auth-server) (nella parte 1 di questo tutorial) consente di specificare le funzionalità dei moderatori. Questa operazione viene eseguita nell'app utilizzando l'oggetto `tokenProvider` creato in [Creazione di un provider di token](chat-sdk-react-tutorial-chat-rooms.md#chat-react-rooms-token-provider) (anch'esso nella parte 1 del tutorial).

Qui puoi modificare il `Message` aggiungendo una funzione per eliminare il messaggio.

Innanzitutto, apri `App.tsx` e aggiungi la funzionalità `DELETE_MESSAGE` (`capabilities` è il secondo parametro della funzione `tokenProvider`).

Nota: in questo modo `ServerApp` informa le API di IVS Chat che l'utente associato al token di chat risultante può eliminare i messaggi in una chat room. In una situazione reale, probabilmente avrai una logica di backend più complessa per gestire le funzionalità degli utenti nell'infrastruttura della tua app server.

**TypeScript/JavaScript**:

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

// ...

const [room] = useState(() =>
    new ChatRoom({
      regionOrUrl: process.env.REGION,
      tokenProvider: () => tokenProvider(userId, ['SEND_MESSAGE', 'DELETE_MESSAGE']),
    }),
);

// ...
```

Nei passaggi successivi, aggiorni il tuo `Message` in modo da visualizzare un pulsante di eliminazione.

Definisci una nuova funzione chiamata `onDelete` che accetta una stringa come uno dei suoi parametri e restituisce `Promise`. Per il parametro string, inserisci l'ID del messaggio del componente.

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

```
// Message.tsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useUserContext } from './UserContext';

export type Props = {
  message: ChatMessage;
  onDelete(id: string): Promise<void>;
};

export const Message = ({ message, onDelete }: Props) => {
  const userId = useUserContext();

  const isMine = message.sender.userId === userId;
  const handleDelete = () => onDelete(message.id);

  return (
    <View style={[styles.root, isMine && styles.mine]}>
      {!isMine && <Text>{message.sender.userId}</Text>}
      <View style={styles.content}>
        <Text style={styles.textContent}>{message.content}</Text>
        <TouchableOpacity onPress={handleDelete}>
          <Text>Delete<Text/>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  content: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
  mine: {
    flexDirection: 'row-reverse',
    backgroundColor: 'lightblue',
  },
});
```

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

```
// Message.jsx

import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useUserContext } from './UserContext';

export const Message = ({ message, onDelete }) => {
  const userId = useUserContext();

  const isMine = message.sender.userId === userId;
  const handleDelete = () => onDelete(message.id);

  return (
    <View style={[styles.root, isMine && styles.mine]}>
      {!isMine && <Text>{message.sender.userId}</Text>}
      <View style={styles.content}>
        <Text style={styles.textContent}>{message.content}</Text>
        <TouchableOpacity onPress={handleDelete}>
          <Text>Delete<Text/>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  root: {
    backgroundColor: 'silver',
    padding: 6,
    borderRadius: 10,
    marginHorizontal: 12,
    marginVertical: 5,
    marginRight: 50,
  },
  content: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  textContent: {
    fontSize: 17,
    fontWeight: '500',
    flexShrink: 1,
  },
  mine: {
    flexDirection: 'row-reverse',
    backgroundColor: 'lightblue',
  },
});
```

------

Successivamente, aggiorna il `renderItem` per riflettere le ultime modifiche apportate al componente `FlatList`.

Quindi, in `App` definisci una funzione denominata `handleDeleteMessage` e passala alla proprietà `MessageList onDelete`.

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

```
// App.tsx

// ...

const handleDeleteMessage = async (id: string) => {};

const renderItem = useCallback<ListRenderItem<ChatMessage>>(({ item }) => {
  return (
    <Message key={item.id} message={item} onDelete={handleDeleteMessage} />
  );
}, [handleDeleteMessage]);

// ...
```

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

```
// App.jsx

// ...

const handleDeleteMessage = async (id) => {};

const renderItem = useCallback(({ item }) => {
  return (
    <Message key={item.id} message={item} onDelete={handleDeleteMessage} />
  );
}, [handleDeleteMessage]);

// ...
```

------

Prepara una richiesta creando una nuova istanza di `DeleteMessageRequest`, passando l'ID messaggio pertinente al parametro del costruttore e una chiamata `deleteMessage` che accetti la richiesta preparata sopra:

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

```
// App.tsx

// ...

const handleDeleteMessage = async (id: string) => {
  const request = new DeleteMessageRequest(id);
  await room.deleteMessage(request);
};

// ...
```

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

```
// App.jsx

// ...

const handleDeleteMessage = async (id) => {
  const request = new DeleteMessageRequest(id);
  await room.deleteMessage(request);
};

// ...
```

------

Successivamente, aggiorna lo stato di `messages` in modo che rifletta un nuovo elenco di messaggi che omette il messaggio appena eliminato.

Nell'hook `useEffect`, ascolta l'evento `messageDelete` e aggiorna il tuo array di stato `messages` eliminando il messaggio con un ID corrispondente al parametro `message`.

Nota: l'evento `messageDelete` potrebbe essere generato quando i messaggi vengono eliminati dall'utente corrente o da qualsiasi altro utente presente nella stanza. Gestirlo nel gestore eventi (anziché accanto alla richiesta `deleteMessage`) consente di unificare la gestione dell'eliminazione dei messaggi.

**TypeScript/JavaScript**:

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

// ...

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

return () => {
  // ...

  unsubscribeOnMessageDeleted();
};

// ...
```

A questo punto puoi eliminare gli utenti da una chat room nella tua app di chat.

## Fasi successive
<a name="chat-react-messages-events-next-steps"></a>

Come esperimento, prova a implementare altre azioni in una stanza, ad esempio la disconnessione di un altro utente.