

# SDK do IVS Chat Client Messaging: Tutorial de JavaScript, parte 2: mensagens e eventos
<a name="chat-sdk-js-tutorial-messages-events"></a>

Esta segunda e última parte do tutorial é dividida em várias seções:

1. [Inscreva-se em eventos de mensagens de chat](#chat-js-messages-events-subscribe)

1. [Exibir mensagens recebidas](#chat-js-messages-events-show)

   1.  [Criação de um componente de mensagem](#chat-js-messages-create-component)

   1. [Reconhecimento das mensagens enviadas pelo usuário atual](#chat-js-messages-recognize)

   1. [Criação de um componente de lista mensagens](#chat-js-messages-create-list-component)

   1. [Renderização de uma lista de mensagens de chat](#chat-js-messages-render-list)

1. [Executar ações em uma sala de chat](#chat-js-messages-events-room-actions)

   1. [Enviar uma mensagem](#chat-js-room-actions-sending-message)

   1. [Excluir mensagem](#chat-js-room-actions-deleting-message)

1. [Próximas etapas](#chat-js-messages-events-next-steps)

**Observação**: em alguns casos, os exemplos de código para JavaScript e TypeScript são idênticos, então eles são combinados.

Para obter a documentação completa do SDK, comece com o [SDK de Mensagens para Clientes do Chat do Amazon IVS](chat-sdk.md) (aqui no *Guia do usuário do Chat do Amazon IVS*) e a [Referência de Mensagens para Clientes do Chat: SDK para JavaScript](https://aws.github.io/amazon-ivs-chat-messaging-sdk-js/latest/) (no GitHub).

## Pré-requisito
<a name="chat-js-messages-events-prerequisite"></a>

Certifique-se de ter concluído a parte 1 deste tutorial, [salas de chat](chat-sdk-js-tutorial-chat-rooms.md).

## Inscreva-se em eventos de mensagens de chat
<a name="chat-js-messages-events-subscribe"></a>

A instância `ChatRoom` usa eventos para se comunicar, quando os eventos ocorrem em uma sala de chat. Para começar a implementar a experiência de chat, você precisa mostrar aos usuários quando as outras pessoas enviam uma mensagem na sala à qual estão conectados.

Aqui, você se inscreve em eventos de mensagens de chat Posteriormente, mostraremos como atualizar uma lista de mensagens que você criou e é atualizada com cada mensagem/evento.

Em seu `App`, dentro do hook `useEffect`, inscreva-se em todos os eventos de mensagens:

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

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

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

## Exibir mensagens recebidas
<a name="chat-js-messages-events-show"></a>

Receber mensagens é parte essencial da experiência de chat. Usando o SDK do Chat JS, é possível configurar seu código para receber facilmente eventos de outros usuários conectados a uma sala de chat.

Posteriormente, mostraremos como realizar ações em uma sala de chat que utilizam os componentes criados por você aqui.

Em sua `App`, defina um estado chamado `messages`, com um tipo de matriz `ChatMessage` chamado `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

// ...

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

  //...
}
```

------

Em seguida, na função de receptor da `message`, acrescente `message` à matriz `messages`:

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

// ...

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

// ...
```

Abaixo, analisamos as tarefas para mostrar as mensagens recebidas:

1.  [Criação de um componente de mensagem](#chat-js-messages-create-component)

1. [Reconhecimento das mensagens enviadas pelo usuário atual](#chat-js-messages-recognize)

1. [Criação de um componente de lista mensagens](#chat-js-messages-create-list-component)

1. [Renderização de uma lista de mensagens de chat](#chat-js-messages-render-list)

### Criação de um componente de mensagem
<a name="chat-js-messages-create-component"></a>

O componente `Message` é responsável por renderizar o conteúdo de uma mensagem recebida pela sua sala de chat. Nesta seção, você cria um componente de mensagens para renderizar mensagens de chat individuais na `App`.

Crie um novo arquivo no diretório `src` e atribua a ele o nome `Message`. Passe o tipo `ChatMessage` para esse componente e, em seguida, passe a string `content` das propriedades de `ChatMessage` para exibir o texto da mensagem recebida dos receptores de mensagens da sala de chat. No Project Navigator, acesse `Message`.

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

```
// Message.tsx

import * as React from 'react';
import { ChatMessage } from 'amazon-ivs-chat-messaging';

type Props = {
  message: ChatMessage;
}

export const Message = ({ message }: Props) => {
  return (
    <div style={{ backgroundColor: 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
    </div>
  );
};
```

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

```
// Message.jsx

import * as React from 'react';

export const Message = ({ message }) => {
  return (
    <div style={{ backgroundColor: 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
    </div>
  );
};
```

------

Dica: use este componente para armazenar propriedades diferentes que você deseja renderizar em suas linhas de mensagens; por exemplo, URLs de avatar, nomes de usuário e carimbos de data/hora de quando a mensagem foi enviada.

### Reconhecimento das mensagens enviadas pelo usuário atual
<a name="chat-js-messages-recognize"></a>

Para reconhecer a mensagem enviada pelo usuário atual, modificamos o código e criamos um contexto do React para armazenar o `userId` do usuário atual.

Crie um novo arquivo no diretório `src` e atribua a ele o nome `UserContext`:

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

```
// UserContext.tsx

import React, { ReactNode, useState, useContext, createContext } from 'react';

type UserContextType = {
  userId: string;
  setUserId: (userId: string) => void;
};

const UserContext = createContext<UserContextType | undefined>(undefined);

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

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

  return context;
};

type UserProviderType = {
  children: ReactNode;
}

export const UserProvider = ({ children }: UserProviderType) => {
  const [userId, setUserId] = useState('Mike');

  return <UserContext.Provider value={{ userId, setUserId }}>{children}</UserContext.Provider>;
};
```

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

```
// UserContext.jsx

import React, { useState, useContext, createContext } from 'react';

const UserContext = createContext(undefined);

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

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

  return context;
};

export const UserProvider = ({ children }) => {
  const [userId, setUserId] = useState('Mike');

  return <UserContext.Provider value={{ userId, setUserId }}>{children}</UserContext.Provider>;
};
```

------

Observação: aqui usamos o hook `useState` para armazenar o valor `userId`. No futuro, será possível usar `setUserId` para alterar o contexto do usuário ou para fins de login.

Em seguida, substitua `userId` no primeiro parâmetro passado para `tokenProvider` usando o contexto criado anteriormente:

```
// App.jsx / 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']),
      }),
  );

  // ...
}
```

Em seu componente `Message`, use o `UserContext` criado antes, declare a variável `isMine`, corresponda o `userId` do remetente com o `userId` do contexto e aplique estilos diferentes de mensagens para o usuário atual.

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

```
// Message.tsx

import * as React from 'react';
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 (
    <div style={{ backgroundColor: isMine ? 'lightblue' : 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
    </div>
  );
};
```

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

```
// Message.jsx

import * as React from 'react';
import { useUserContext } from './UserContext';

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

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

  return (
    <div style={{ backgroundColor: isMine ? 'lightblue' : 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
    </div>
  );
};
```

------

### Criação de um componente de lista mensagens
<a name="chat-js-messages-create-list-component"></a>

O componente `MessageList` é responsável por exibir a conversa de uma sala de chat ao longo do tempo. O arquivo `MessageList` é o contêiner que contém todas as nossas mensagens. `Message` é uma linha de `MessageList`.

Crie um novo arquivo no diretório `src` e atribua a ele o nome `MessageList`. Defina `Props` com `messages` do tipo matriz de `ChatMessage`. Dentro do corpo, mapeie nossa propriedade `messages` e passe `Props` para seu componente `Message`.

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

```
// MessageList.tsx

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

interface Props {
  messages: ChatMessage[];
}

export const MessageList = ({ messages }: Props) => {
  return (
    <div>
      {messages.map((message) => (
        <Message key={message.id} message={message}/>
      ))}
    </div>
  );
};
```

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

```
// MessageList.jsx

import React from 'react';
import { Message } from './Message';

export const MessageList = ({ messages }) => {
  return (
    <div>
      {messages.map((message) => (
        <Message key={message.id} message={message} />
      ))}
    </div>
  );
};
```

------

### Renderização de uma lista de mensagens de chat
<a name="chat-js-messages-render-list"></a>

Agora, coloque o novo `MessageList` em seu componente `App` principal:

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

import { MessageList } from './MessageList';
// ...

return (
  <div style={{ display: 'flex', flexDirection: 'column', padding: 10 }}>
    <h4>Connection State: {connectionState}</h4>
    <MessageList messages={messages} />
    <div style={{ flexDirection: 'row', display: 'flex', width: '100%', backgroundColor: 'red' }}>
      <MessageInput value={messageToSend} onValueChange={setMessageToSend} />
      <SendButton disabled={isSendDisabled} onPress={onMessageSend} />
    </div>
  </div>
);

// ...
```

Todas as peças do quebra-cabeça estão prontas para que sua `App` comece a renderizar as mensagens recebidas pela sua sala de chat. Continue abaixo para ver como realizar ações em uma sala de chat que aproveitem os componentes que você criou.

## Executar ações em uma sala de chat
<a name="chat-js-messages-events-room-actions"></a>

Enviar mensagens e realizar ações de moderador em uma sala de chat são algumas das principais formas de interagir com uma sala de chat. Aqui você aprenderá como usar vários objetos `ChatRequest` para realizar ações comuns no Chatterbox, como enviar uma mensagem, excluir uma mensagem e desconectar outros usuários.

Todas as ações em uma sala de chat seguem um padrão comum: para cada ação executada em uma sala de chat, há um objeto de solicitação correspondente. Para cada solicitação, há um objeto de resposta correspondente que você recebe na confirmação da solicitação.

Desde que seus usuários recebam as permissões corretas quando você criar um token de chat, eles poderão realizar com êxito as ações correspondentes usando os objetos de solicitação para ver quais solicitações são possíveis de ser realizadas em uma sala de chat.

Abaixo, explicamos como [enviar uma mensagem](#chat-js-room-actions-sending-message) e [excluir uma mensagem](#chat-js-room-actions-deleting-message).

### Enviar uma mensagem
<a name="chat-js-room-actions-sending-message"></a>

A classe `SendMessageRequest` permite o envio de mensagens em uma sala de chat. Aqui, você modifica sua `App` para enviar uma solicitação de mensagem usando o componente que criou em [Criar uma entrada de mensagem](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-message-input) (na parte 1 deste tutorial).

Para começar, defina uma nova propriedade booleana chamada de `isSending` com o hook `useState`. Use essa nova propriedade para alternar o estado desativado do seu elemento HTML `button` usando a constante `isSendDisabled`. No manipulador de eventos do seu `SendButton`, limpe o valor de `messageToSend` e defina `isSending` como verdadeiro.

*Como você fará uma chamada de API a partir desse botão, adicionar o booleano `isSending` ajuda a evitar que várias chamadas de API ocorram ao mesmo tempo, desativando as interações do usuário no seu `SendButton` até que a solicitação seja concluída.*

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

// ...

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

// ...

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

// ...

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

// ...
```

Prepare a solicitação criando uma nova instância `SendMessageRequest`, passando o conteúdo da mensagem para o construtor. Depois de definir os estados `isSending` e `messageToSend`, chame o método `sendMessage`, que envia a solicitação para a sala de chat. Por fim, limpe o sinalizador `isSending` ao receber a confirmação ou rejeição da solicitação.

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

```
// App.tsx

// ...
import { ChatMessage, 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);
  }
};

// ...
```

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

```
// App.jsx

// ...
import { ChatRoom, 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);
  }
};

// ...
```

------

Experimente o Chatterbox: tente enviar uma mensagem redigindo uma com a sua `MessageInput` e tocando no seu `SendButton`. Você deve ver sua mensagem enviada renderizada dentro da `MessageList` que você criou anteriormente.

### Excluir mensagem
<a name="chat-js-room-actions-deleting-message"></a>

Para excluir uma mensagem de uma sala de chat, você precisa ter a capacidade adequada. As capacidades são concedidas durante a inicialização do token de chat que você usa ao se autenticar em uma sala de chat. Para os propósitos desta seção, a `ServerApp` de [Configure um servidor local de autenticação/autorização](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-auth-server) (na parte 1 deste tutorial) permite que você especifique as capacidades de moderador. Isso é feito em sua aplicação usando o objeto `tokenProvider` que você criou em [Crie um provedor de tokens](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-token-provider) (também na parte 1).

Aqui você modifica sua `Message` adicionando uma função para excluir a mensagem.

Primeiro, abra `App.tsx` e adicione a capacidade `DELETE_MESSAGE`. (`capabilities` é o segundo parâmetro da sua função `tokenProvider`.)

Observação: é assim que sua `ServerApp` informa às APIs do IVS Chat que o usuário associado ao token de chat resultante pode excluir mensagens em uma sala de chat. Em uma situação real, você provavelmente terá uma lógica de backend mais complexa para gerenciar os recursos do usuário na infraestrutura da sua aplicação de servidor.

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

```
// App.tsx

// ...

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

// ...
```

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

```
// App.jsx

// ...

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

// ...
```

------

Nas próximas etapas, você atualizará sua `Message` para exibir um botão de exclusão.

Abra `Message` e defina um novo estado booleano chamado `isDeleting` usando o hook `useState` com um valor inicial de `false`. Usando esse estado, atualize o conteúdo do seu `Button` para ser diferente, dependendo do estado atual de `isDeleting`. Desative seu botão quando `isDeleting` for verdadeiro. Isso evita que você tente fazer duas solicitações de exclusão de mensagens ao mesmo tempo. 

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

```
// Message.tsx

import React, { useState } from 'react';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { useUserContext } from './UserContext';

type Props = {
  message: ChatMessage;
}

export const Message = ({ message }: Props) => {
  const { userId } = useUserContext();
  const [isDeleting, setIsDeleting] = useState(false);

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

  return (
    <div style={{ backgroundColor: isMine ? 'lightblue' : 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
      <button disabled={isDeleting}>Delete</button>
    </div>
  );
};
```

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

```
// Message.jsx

import React from 'react';
import { useUserContext } from './UserContext';

export const Message = ({ message }) => {
  const { userId } = useUserContext();
  const [isDeleting, setIsDeleting] = useState(false);

  return (
    <div style={{ backgroundColor: isMine ? 'lightblue' : 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
      <button disabled={isDeleting}>Delete</button>
    </div>
  );
};
```

------

Defina uma nova função chamada `onDelete` que aceite uma string como um de seus parâmetros e retorne `Promise`. No corpo do encerramento da ação do seu `Button`, use `setIsDeleting` para alternar seu booleano `isDeleting` antes e depois de uma chamada para `onDelete`. Para o parâmetro de string, passe o ID da mensagem do componente.

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

```
// Message.tsx

import React, { useState } from 'react';
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 [isDeleting, setIsDeleting] = useState(false);
  const isMine = message.sender.userId === userId;
  const handleDelete = async () => {
    setIsDeleting(true);
    try {
      await onDelete(message.id);
    } catch (e) {
      console.log(e);
      // handle chat error here...
    } finally {
      setIsDeleting(false);
    }
  };

  return (
    <div style={{ backgroundColor: isMine ? 'lightblue' : 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{content}</p>
      <button onClick={handleDelete} disabled={isDeleting}>
        Delete
      </button>
    </div>
  );
};
```

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

```
// Message.jsx

import React, { useState } from 'react';
import { useUserContext } from './UserContext';

export const Message = ({ message, onDelete }) => {
  const { userId } = useUserContext();
  const [isDeleting, setIsDeleting] = useState(false);
  const isMine = message.sender.userId === userId;
  const handleDelete = async () => {
    setIsDeleting(true);
    try {
      await onDelete(message.id);
    } catch (e) {
      console.log(e);
      // handle the exceptions here...
    } finally {
      setIsDeleting(false);
    }
  };

  return (
    <div style={{ backgroundColor: 'silver', padding: 6, borderRadius: 10, margin: 10 }}>
      <p>{message.content}</p>
      <button onClick={handleDelete} disabled={isDeleting}>
        Delete
      </button>
    </div>
  );
};
```

------

Em seguida, atualize sua `MessageList` para refletir as alterações mais recentes em seu componente `Message`.

Abra `MessageList` e defina uma nova função chamada `onDelete` que aceite uma string como um parâmetro e retorne `Promise`. Atualize a `Message` e passe-a pelas propriedades da `Message`. O parâmetro de string em seu novo encerramento será o ID da mensagem que você deseja excluir, que será passada a partir da sua `Message`.

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

```
// MessageList.tsx

import * as React from 'react';
import { ChatMessage } from 'amazon-ivs-chat-messaging';
import { Message } from './Message';

interface Props {
  messages: ChatMessage[];
  onDelete(id: string): Promise<void>;
}

export const MessageList = ({ messages, onDelete }: Props) => {
  return (
    <>
      {messages.map((message) => (
        <Message key={message.id} onDelete={onDelete} content={message.content} id={message.id} />
      ))}
    </>
  );
};
```

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

```
// MessageList.jsx

import * as React from 'react';
import { Message } from './Message';

export const MessageList = ({ messages, onDelete }) => {
  return (
    <>
      {messages.map((message) => (
        <Message key={message.id} onDelete={onDelete} content={message.content} id={message.id} />
      ))}
    </>
  );
};
```

------

Em seguida, você atualiza sua `App` para refletir as alterações mais recentes em sua `MessageList`.

Em `App`, defina uma função chamada `onDeleteMessage` e passe-a para a propriedade `MessageList onDelete`.

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

```
// App.tsx

// ...

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

return (
  <div style={{ display: 'flex', flexDirection: 'column', padding: 10 }}>
    <h4>Connection State: {connectionState}</h4>
    <MessageList onDelete={onDeleteMessage} messages={messages} />
    <div style={{ flexDirection: 'row', display: 'flex', width: '100%' }}>
      <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
      <SendButton disabled={isSendDisabled} onSendPress={onMessageSend} />
    </div>
  </div>
);

// ...
```

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

```
// App.jsx

// ...

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

return (
  <div style={{ display: 'flex', flexDirection: 'column', padding: 10 }}>
    <h4>Connection State: {connectionState}</h4>
    <MessageList onDelete={onDeleteMessage} messages={messages} />
    <div style={{ flexDirection: 'row', display: 'flex', width: '100%' }}>
      <MessageInput value={messageToSend} onMessageChange={setMessageToSend} />
      <SendButton disabled={isSendDisabled} onSendPress={onMessageSend} />
    </div>
  </div>
);

// ...
```

------

Prepare uma solicitação criando uma nova instância de `DeleteMessageRequest`, passando o ID da mensagem relevante para o parâmetro do construtor e chame `deleteMessage`, que aceita a solicitação preparada acima:

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

```
// App.tsx

// ...

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

// ...
```

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

```
// App.jsx

// ...

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

// ...
```

------

Em seguida, atualize o estado de `messages` para refletir uma nova lista de mensagens que omita a mensagem que você acabou de excluir.

No hook `useEffect`, receba o evento `messageDelete` e atualize sua matriz de estados de `messages` excluindo a mensagem com um ID correspondente ao parâmetro `message`.

Observação: o evento `messageDelete` pode ser gerado para que as mensagens sejam excluídas pelo usuário atual ou por qualquer outro usuário na sala. Manipulá-lo no manipulador de eventos (em vez de junto à solicitação `deleteMessage`) permite unificar o tratamento da exclusão de mensagens.

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

// ...

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

return () => {
  // ...

  unsubscribeOnMessageDeleted();
};

// ...
```

Agora é possível excluir usuários de uma sala de chat na sua aplicação de chat.

## Próximas etapas
<a name="chat-js-messages-events-next-steps"></a>

A título de experimento, tente implementar outras ações em uma sala, como desconectar um outro usuário.