7.
チャットボット(フロントエンド 2)
メッセージ表示処理
ファイル構成
my-app/
├── app/
│ ├── api/
│ │ └── chat/
│ │ └── route.ts
│ ├── interfaces/
│ │ └── Message.ts
│ └── page.tsx
├── styles/
│ └── globals.css
├── .env.local
├── tailwind.config.js
├── tsconfig.json
├── package.json
└── .gitignore
ページコンポーネント
チャット一覧データ定義
チャット一覧データ「messages」を定義します。
app/page.ts
// Messageインターフェースインポート
import { Message } from '@/app/interfaces/Message';
export default function Home() {
const [inputMessage, setInputMessage] = useState<string>('');
// チャット一覧データ定義
const [messages, setMessages] = useState<Message[]>([]);
...
}
- 「interfaces/Message.ts」をインポートが必要です。
チャット一覧表示
テキストボックスで入力したデータを setMessges() で設定し、チャット一覧に表示します。
app/page.ts
import { Message } from '@/app/interfaces/Message';
export default function Home() {
...
const sendHandler = async () => {
if (inputMessage.trim() === '') return;
// チャットデータ作成
const message: Message = { sender: 'user', message: inputMessage };
// チャットデータ設定
setMessages(prevMessages => [message, ...prevMessages]);
setInputMessage('');
};
...
}
チャットデータ表示
「messages」を繰り返し表示するよう、JSXを追加します。
app/page.ts
'use client';
import { useState, useRef, useEffect } from "react";
import { Message } from "@/app/interfaces/Message";
export default function Home() {
...
return (
<main className="flex flex-col justify-center">
<div className="bg-white shadow-md p-4 z-10">
<h1 className="text-2xl p-5">Gemini Chatbot</h1>
...
</div>
{/* メッセージ繰り返し */}
<div className="p-4 mb-4 overflow-y-scroll">
{messages && messages.map((message, index) => (
<div
key={index}
className="m-3 p-5 border border-gray-100 rounded">
<span className={
`inline-block mb-2 me-3 px-3 py-1
rounded-full text-white
text-sm font-semibold
${message.sender === 'user' ? 'bg-blue-600' : 'bg-gray-600'}
`}>
{message.sender === 'user' ? 'あなた' : 'ボット'}
</span>
<span>{message.message}</span>
</div>
))}
</div>
</main>
);
}
動作確認
テキストボックスのデータを送信するたびに、メッセージが表示されました。

API通信
axiosインストール
「axios」パッケージをインストールします。
ターミナル
npm i axios
POSTリクエスト
axios で「/api/chat」に対して、「message」をPOSTリクエストします。
app/page.ts
const sendHandler = async () => {
if (inputMessage.trim() === '') return;
const message: Message = { sender: 'user', content: inputMessage };
setMessages(prevMessages => [message, ...prevMessages]);
// /api/chat にPOSTリクエスト
const uri = "/api/chat";
const response = await axios.post(uri, message);
console.log(response)
};
- await で非同期通信します。
ボットメッセージ追加
APIから受け取ったボットメッセージを、チャット一覧に追加します。
app/page.ts
const sendHandler = async () => {
if (inputMessage.trim() === '') return;
const message: Message = { sender: 'user', content: inputMessage };
setMessages(prevMessages => [message, ...prevMessages]);
const uri = "/api/chat";
const response = await axios.post(uri, message);
// ボットメッセージをチャット一覧に追加
const botMessage: Message = response.data.bot;
setMessages(prevMessages => [botMessage, ...prevMessages]);
setInputMessage('');
};
動作確認
データを送信して、Gemini APIの回答が表示されるか確認してみましょう。

問題点
質問によっては、Gemini APIの回答がマークダウンでレスポンスされるため、思うような表示ができない問題があります。

これを解決するには、以下のような対策が考えられます。
- マークダウンをHTMLで表示
- マークダウンを整形
- JSON、CSVなどの定型フォーマットでレスポンス