1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人的備忘録:FastAPI × Next.jsでAI応答を受け取り、画面に表示する仕組みを実装してみた

Posted at

はじめに

Next.js(React)と FastAPI を連携したアプリケーションで、ユーザーが日記を投稿すると、AI(さぶちゃん)からの応援メッセージが返ってくる機能を実装しています。

本記事では、返答内容を「さぶちゃんからの熱いエール」欄に画面表示する方法を紹介します。

書こうと思ったきっかけ

受講しているITスクールのハッカソンの開発の一環で、日記投稿後の返答メッセージを見せる仕組みを作ろうとした際に、応答の扱いと表示形式の工夫が必要だったため、記録としてまとめました。

実際の画面(開発中)

Screenshot 2025-05-08 at 8.20.44.png

実際の画面(一旦、完成画面)

Screenshot 2025-05-08 at 8.21.06.png

内容

以下は実際に使用している SabutyanMode コンポーネントの抜粋コードです。応援メッセージの表示に関係する部分を中心に紹介します。

状態管理

const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");

ユーザーが入力した日記(diaryMessage)と、APIからの応答メッセージ(cheerMessage)を別々の状態で管理しています。

応援メッセージの取得処理

const handleEnergy = async () => {
  if (!sessionId) {
    alert("セッションIDが見つかりません");
    return;
  }

  try {
    const payload = {
      session_id: Number(sessionId),
      is_user: true,
      content: diaryMessage,
    };

    const res = await fetch(`http://localhost:8000/api/sessions/${sessionId}/messages`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    if (!res.ok) throw new Error("送信に失敗しました");

    const result = await res.json();
    setCheerMessage(result.content || "さぶちゃんから応援が届きました!");
  } catch (error) {
    console.error("エラー:", error);
    alert("エラーが発生しました");
  }
};

API のレスポンスから result.content を取得し、それを cheerMessage にセットしています。

応援メッセージの表示エリア

<div className="w-full h-32 border border-gray-300 rounded-md p-3 bg-[#fffaf0] whitespace-pre-wrap overflow-y-auto">
  {cheerMessage || "ここにさぶちゃんの応援が表示されます"}
</div>

この表示専用 div によって、API から受け取った応援メッセージがリアルタイムに画面に表示される仕組みとなっています。

起きていた問題

  • 日記欄と応援メッセージ欄に同じ状態変数を使っていたため、文字が連動していた
  • 応援メッセージを表示させたいが、textarea ではユーザーが編集できてしまう

修正内容

1. 状態管理を分離

const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");

2. FastAPI 応答を cheerMessage にセット

const result = await res.json();
setCheerMessage(result.content || "さぶちゃんから応援が届きました!");

3. 表示専用のエール欄を div に変更

<div className="w-full h-32 border border-gray-300 rounded-md p-3 bg-[#fffaf0] whitespace-pre-wrap overflow-y-auto">
  {cheerMessage || "ここにさぶちゃんの応援が表示されます"}
</div>
  • textarea を div に変更し、ユーザーが編集できないように
  • whitespace-pre-wrap によって改行も反映

まとめ

フォームで状態変数を共通化すると文字が連動してしまうため、用途ごとに状態を分ける必要があります。

また、表示専用の応答欄には div を用いて、ユーザーが内容を編集できないようにすることが重要です。

これにより、ユーザーが入力した日記に対して、さぶちゃんからの応援を自然な形で表示できるようになりました...!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?