

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# SDK Pesan Klien Obrolan IVS: JavaScript Tutorial Bagian 2: Pesan dan Acara
<a name="chat-sdk-js-tutorial-messages-events"></a>

Bagian kedua (dan terakhir) dari tutorial ini dipecah menjadi beberapa bagian:

1. [Berlangganan Peristiwa Pesan Obrolan](#chat-js-messages-events-subscribe)

1. [Menampilkan Pesan yang Diterima](#chat-js-messages-events-show)

   1.  [Membuat Komponen Pesan](#chat-js-messages-create-component)

   1. [Mengenali Pesan yang Dikirim oleh Pengguna Saat Ini](#chat-js-messages-recognize)

   1. [Membuat Komponen Daftar Pesan](#chat-js-messages-create-list-component)

   1. [Me-render Daftar Pesan Obrolan](#chat-js-messages-render-list)

1. [Melakukan Tindakan di Ruang Obrolan](#chat-js-messages-events-room-actions)

   1. [Mengirim Pesan](#chat-js-room-actions-sending-message)

   1. [Menghapus Pesan](#chat-js-room-actions-deleting-message)

1. [Langkah Berikutnya](#chat-js-messages-events-next-steps)

**Catatan**: Dalam beberapa kasus, contoh kode untuk JavaScript dan TypeScript identik, sehingga digabungkan.

Untuk dokumentasi SDK lengkap, mulailah dengan [Amazon IVS Chat Client Messaging SDK](chat-sdk.md) (di sini, di *Panduan Pengguna Obrolan Amazon IVS*) dan [Pesan Klien Obrolan: SDK untuk JavaScript ](https://aws.github.io/amazon-ivs-chat-messaging-sdk-js/latest/) Referensi (aktif). GitHub

## Prasyarat
<a name="chat-js-messages-events-prerequisite"></a>

Pastikan Anda telah menyelesaikan Bagian 1 dari tutorial ini, [Ruang Obrolan](chat-sdk-js-tutorial-chat-rooms.md).

## Berlangganan Peristiwa Pesan Obrolan
<a name="chat-js-messages-events-subscribe"></a>

Instans `ChatRoom` menggunakan peristiwa untuk berkomunikasi ketika peristiwa terjadi di ruang obrolan. Untuk mulai mengimplementasikan pengalaman obrolan, Anda harus menunjukkan kepada pengguna saat orang lain mengirim pesan di ruang yang terhubung dengan mereka.

Di sini, Anda berlangganan peristiwa pesan obrolan. Selanjutnya, kami akan menunjukkan cara memperbarui daftar pesan yang Anda buat, yang diperbarui dengan setiap pesan/peristiwa.

Di `App` Anda, di dalam hook `useEffect`, berlangganan semua peristiwa pesan:

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

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

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

## Menampilkan Pesan yang Diterima
<a name="chat-js-messages-events-show"></a>

Menerima pesan adalah bagian inti dari pengalaman obrolan. Dengan SDK JS Obrolan, Anda dapat menyiapkan kode agar dapat dengan mudah menerima peristiwa dari pengguna lain yang terhubung ke ruang obrolan.

Selanjutnya, kami akan menunjukkan cara melakukan tindakan di ruang obrolan yang memanfaatkan komponen yang Anda buat di sini.

Di `App` Anda, tentukan status bernama `messages` dengan tipe array `ChatMessage` yang bernama `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([]);

  //...
}
```

------

Selanjutnya, di fungsi pendengar `message`, tambahkan `message` ke array `messages`:

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

// ...

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

// ...
```

Di bawah ini, kita akan menjalankan langkah demi langkah untuk menampilkan pesan yang diterima:

1.  [Membuat Komponen Pesan](#chat-js-messages-create-component)

1. [Mengenali Pesan yang Dikirim oleh Pengguna Saat Ini](#chat-js-messages-recognize)

1. [Membuat Komponen Daftar Pesan](#chat-js-messages-create-list-component)

1. [Me-render Daftar Pesan Obrolan](#chat-js-messages-render-list)

### Membuat Komponen Pesan
<a name="chat-js-messages-create-component"></a>

Komponen `Message` bertanggung jawab untuk me-render konten pesan yang diterima oleh ruang obrolan Anda. Di bagian ini, Anda membuat komponen pesan untuk me-render pesan obrolan individu di `App`.

Buat file baru di direktori `src` dan beri nama `Message`. Berikan tipe `ChatMessage` untuk komponen ini, dan berikan string `content` dari properti `ChatMessage` untuk menampilkan teks pesan yang diterima dari pendengar pesan ruang obrolan. Di Navigator Proyek, buka `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>
  );
};
```

------

Tip: Gunakan komponen ini untuk menyimpan properti berbeda yang ingin Anda render di baris pesan; misalnya, avatar URLs, nama pengguna, dan cap waktu saat pesan dikirim.

### Mengenali Pesan yang Dikirim oleh Pengguna Saat Ini
<a name="chat-js-messages-recognize"></a>

Untuk mengenali pesan yang dikirim oleh pengguna saat ini, kita mengubah kode dan membuat konteks React untuk menyimpan `userId` pengguna saat ini.

Buat file baru di direktori `src` dan beri nama `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>;
};
```

------

Catatan: Di sini kita menggunakan hook `useState` untuk menyimpan nilai `userId`. Ke depannya, Anda dapat menggunakan `setUserId` untuk mengubah konteks pengguna atau untuk tujuan login.

Selanjutnya, ganti `userId` pada parameter pertama yang diberikan ke `tokenProvider`, dengan menggunakan konteks yang dibuat sebelumnya:

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

  // ...
}
```

Dalam komponen `Message` Anda, gunakan `UserContext` yang dibuat sebelumnya, nyatakan variabel `isMine`, cocokkan `userId` pengirim dengan `userId` dari konteks, dan terapkan gaya pesan yang berbeda untuk pengguna saat ini.

------
#### [ 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>
  );
};
```

------

### Membuat Komponen Daftar Pesan
<a name="chat-js-messages-create-list-component"></a>

Komponen `MessageList` bertanggung jawab untuk menampilkan percakapan ruang obrolan dari waktu ke waktu. File `MessageList` ini adalah kontainer yang menyimpan semua pesan kita. `Message` adalah satu baris di `MessageList`.

Buat file baru di direktori `src` dan beri nama `MessageList`. Tentukan `Props` dengan `messages` tipe array `ChatMessage`. Di dalam isi, petakan properti `messages` dan teruskan `Props` ke komponen `Message` Anda.

------
#### [ 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>
  );
};
```

------

### Me-render Daftar Pesan Obrolan
<a name="chat-js-messages-render-list"></a>

Sekarang bawa `MessageList` baru ke komponen `App` utama Anda:

```
// 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>
);

// ...
```

Semua potongan puzzle sekarang sudah siap sehingga `App` Anda dapat mulai me-render pesan yang diterima oleh ruang obrolan Anda. Lanjutkan langkah di bawah ini untuk melihat cara melakukan tindakan di ruang obrolan yang memanfaatkan komponen yang telah Anda buat.

## Melakukan Tindakan di Ruang Obrolan
<a name="chat-js-messages-events-room-actions"></a>

Mengirim pesan dan melakukan tindakan moderator dalam ruang obrolan adalah beberapa cara utama Anda dalam berinteraksi dengan ruang obrolan. Di sini, Anda akan belajar cara menggunakan berbagai objek `ChatRequest` untuk melakukan tindakan umum di Chatterbox, seperti mengirim pesan, menghapus pesan, dan memutus koneksi pengguna lain.

Semua tindakan di ruang obrolan mengikuti pola umum: untuk setiap tindakan yang Anda lakukan di ruang obrolan, ada objek permintaan yang sesuai. Untuk setiap permintaan, ada objek respons yang sesuai yang Anda terima setelah konfirmasi permintaan.

Selama pengguna Anda diberi izin yang benar saat Anda membuat token obrolan, mereka akan berhasil melakukan tindakan yang sesuai menggunakan objek permintaan untuk melihat permintaan apa yang dapat Anda lakukan di ruang obrolan.

Di bawah ini, kami menjelaskan cara [mengirim pesan](#chat-js-room-actions-sending-message) dan [menghapus pesan](#chat-js-room-actions-deleting-message).

### Mengirim Pesan
<a name="chat-js-room-actions-sending-message"></a>

Kelas `SendMessageRequest` memungkinkan pengiriman pesan di ruang obrolan. Di sini, Anda memodifikasi `App` untuk mengirim permintaan pesan menggunakan komponen yang Anda buat di [Buat Input Pesan](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-message-input) (di Bagian 1 tutorial ini).

Untuk memulai, tentukan properti boolean baru bernama `isSending` dengan hook `useState`. Gunakan properti baru ini untuk mengaktifkan status nonaktif elemen HTML `button` Anda, dengan menggunakan konstanta `isSendDisabled`. Di handler peristiwa untuk `SendButton` Anda, kosongkan nilai untuk `messageToSend` dan atur `isSending` ke true.

*Karena Anda akan melakukan panggilan API dari tombol ini, penambahan boolean `isSending` akan membantu mencegah banyaknya panggilan API yang terjadi di waktu yang bersamaan, dengan menonaktifkan interaksi pengguna pada `SendButton` Anda hingga permintaan selesai.*

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

// ...

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

// ...

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

// ...

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

// ...
```

Siapkan permintaan dengan membuat instans `SendMessageRequest` baru, dengan meneruskan konten pesan ke konstruktor. Setelah mengatur status `isSending` dan `messageToSend`, panggil metode `sendMessage`, yang mengirimkan permintaan ke ruang obrolan. Terakhir, hapus bendera `isSending` saat menerima konfirmasi atau penolakan permintaan.

------
#### [ 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);
  }
};

// ...
```

------

Jalankan Chatterbox: coba mengirim pesan dengan menyusun pesan menggunakan `MessageInput` Anda dan mengetuk `SendButton` Anda. Anda akan melihat pesan terkirim Anda di-render dalam `MessageList` yang dibuat sebelumnya.

### Menghapus Pesan
<a name="chat-js-room-actions-deleting-message"></a>

Untuk menghapus pesan dari ruang obrolan, Anda harus memiliki kemampuan yang tepat. Kemampuan diberikan selama inisialisasi token obrolan yang Anda gunakan saat mengautentikasi ke ruang obrolan. Untuk keperluan bagian ini, `ServerApp` dari [Menyiapkan Server Autentikasi/Otorisasi Lokal](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-auth-server) (di Bagian 1 tutorial ini) memungkinkan Anda menentukan kemampuan moderator. Hal ini dilakukan di aplikasi Anda menggunakan objek `tokenProvider` yang Anda buat di [Membangun Penyedia Token](chat-sdk-js-tutorial-chat-rooms.md#chat-js-rooms-token-provider) (juga di Bagian 1).

Di sini, Anda memodifikasi `Message` dengan menambahkan fungsi untuk menghapus pesan.

Pertama, buka `App.tsx` dan tambahkan kemampuan `DELETE_MESSAGE`. (`capabilities` adalah parameter kedua dari fungsi `tokenProvider` Anda.)

Catatan: Ini adalah cara Anda `ServerApp` menginformasikan Obrolan IVS APIs bahwa pengguna yang dikaitkan dengan token obrolan yang dihasilkan dapat menghapus pesan di ruang obrolan. Dalam situasi dunia nyata, Anda mungkin akan memiliki logika backend yang lebih kompleks untuk mengelola kemampuan pengguna di infrastruktur aplikasi server Anda.

------
#### [ 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']),
  }),
);

// ...
```

------

Pada langkah berikutnya, Anda memperbarui `Message` untuk menampilkan tombol hapus.

Buka `Message` dan tentukan status boolean baru yang bernama `isDeleting` menggunakan hook `useState` dengan nilai awal `false`. Dengan menggunakan status ini, perbarui konten `Button` Anda menjadi berbeda, tergantung status `isDeleting` saat ini. Nonaktifkan tombol Anda ketika `isDeleting` true; hal ini mencegah Anda dari mencoba untuk membuat dua permintaan penghapusan pesan di waktu yang bersamaan. 

------
#### [ 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>
  );
};
```

------

Tentukan fungsi baru bernama `onDelete`, yang menerima string sebagai salah satu parameternya dan mengembalikan `Promise`. Di dalam isi penutupan tindakan `Button` Anda, gunakan `setIsDeleting` untuk mengalihkan boolean `isDeleting` sebelum dan sesudah panggilan ke `onDelete`. Untuk parameter string, berikan ID pesan komponen Anda.

------
#### [ 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>
  );
};
```

------

Selanjutnya, Anda memperbarui `MessageList` untuk merefleksikan perubahan terbaru pada komponen `Message` Anda.

Buka `MessageList` dan tentukan fungsi baru yang disebut `onDelete`, yang menerima string sebagai parameter dan mengembalikan `Promise`. Perbarui `Message` Anda dan teruskan melalui properti `Message`. Parameter string dalam penutupan baru Anda akan menjadi ID pesan yang ingin dihapus, yang diteruskan dari `Message` Anda.

------
#### [ 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} />
      ))}
    </>
  );
};
```

------

Selanjutnya, Anda memperbarui `App` untuk menunjukkan perubahan terbaru pada `MessageList` Anda.

Di `App`, tentukan fungsi bernama `onDeleteMessage` dan teruskan ke properti `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>
);

// ...
```

------

Siapkan permintaan dengan membuat instans `DeleteMessageRequest` baru, dengan meneruskan ID pesan yang relevan ke parameter konstruktor, dan panggil `deleteMessage` yang menerima permintaan yang disiapkan di atas:

------
#### [ 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);
};

// ...
```

------

Selanjutnya, Anda memperbarui status `messages` untuk merefleksikan daftar pesan baru yang menghilangkan pesan yang baru saja Anda hapus.

Di hook `useEffect`, dengarkan peristiwa `messageDelete` dan perbarui array status `messages` Anda dengan menghapus pesan yang mempunyai ID yang sama dengan parameter `message`.

Catatan: Peristiwa `messageDelete` dapat dimunculkan untuk pesan yang dihapus oleh pengguna saat ini atau pengguna lain di ruang. Dengan menanganinya di handler peristiwa (bukan di samping permintaan `deleteMessage`), Anda dapat menyatukan penanganan hapus-pesan.

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

// ...

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

return () => {
  // ...

  unsubscribeOnMessageDeleted();
};

// ...
```

Sekarang Anda dapat menghapus pengguna dari ruang obrolan di aplikasi obrolan Anda.

## Langkah Berikutnya
<a name="chat-js-messages-events-next-steps"></a>

Sebagai percobaan, coba implementasikan tindakan lain di suatu ruang, seperti memutus koneksi pengguna lain.