2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

保存ボタンを2回押すと、データが2件登録される — AIに頼むだけでは抜けやすい二重送信対策

2
Posted at

はじめに

Claude Codeに「保存ボタンを押したらメモを登録する機能を作って」と頼むと、フォームの送信処理がすぐに実装されます。1回押して確認する分には、ちゃんと1件登録され、動作確認も問題なく通ることが多いです。

ただ、通信が少し遅い環境で試したり、焦って早くボタンを押したりすると、同じ内容のメモが2件、3件と登録されてしまうことがあります。これは実装が間違っているわけではなく、「連続で押されたときにどうするか」という条件が、最初の依頼には含まれていなかっただけです。

本記事では、二重送信が起きる仕組みと、AIに実装を頼むときに伝えておくと防げる観点を、コード例つきで紹介します。

なぜ2回押しただけで2件登録されるのか

保存ボタンを押すと、サーバーにデータを送るリクエストが1回発生します。ボタンを2回押せば、リクエストも単純に2回発生します。

async function handleSave() {
  await fetch("/api/memos", {
    method: "POST",
    body: JSON.stringify({ text: memoText }),
  });
}

この処理には、「今リクエストを送信中かどうか」という状態がどこにも記録されていません。ボタンがまだ押せる状態のままなので、1回目のリクエストが終わる前に2回目を押すと、そのまま2回目のリクエストも飛んでいきます。

見た目上は保存が終わって画面が切り替わるので、押した本人は「2回押したこと」に気づきにくいことがあります。気づくのは、後から一覧を見て同じメモが2つ並んでいるのを発見したときです。

送信中はボタンを押せなくする

いちばん基本的な対策は、リクエストが完了するまでボタンを無効化することです。

const [isSaving, setIsSaving] = useState(false);

async function handleSave() {
  if (isSaving) return;
  setIsSaving(true);
  try {
    await fetch("/api/memos", {
      method: "POST",
      body: JSON.stringify({ text: memoText }),
    });
  } finally {
    setIsSaving(false);
  }
}
<button onClick={handleSave} disabled={isSaving}>
  {isSaving ? "保存中..." : "保存"}
</button>

isSavingtrue の間はボタンが押せなくなるので、通信中に連打しても2回目以降のクリックは無視されます。ボタンの表示を「保存中...」に変えておくと、押した本人にも「今処理が進んでいる」ことが伝わります。

クライアント側の対策だけでは足りない場合もある

ボタンの無効化はクリック連打には効きますが、通信が不安定でブラウザが同じリクエストを自動的に再送するケースや、複数タブで同じ画面を開いているケースまでは防げません。

より確実にしたい場合は、サーバー側でも「同じ内容の登録が短時間に連続していないか」をチェックする、あるいはリクエストごとに一意なIDを振って、同じIDのリクエストは2回目以降を無視する、という対策を組み合わせます。ただし、未経験のうちはまず「ボタンを無効化する」というクライアント側の対策から押さえておけば、クリック連打による二重送信への対策としては十分です。

AIに実装を頼むときに伝えておくこと

「保存機能をつけて」とだけ頼むのではなく、「保存中はボタンを押せないようにして、連打しても2回登録されないようにしてください」と、二重送信への対応まで含めて伝えておくと、この手の見落としを事前に防げます。

依頼した後であれば、「このボタンは連打されたとき、リクエストが2回飛びませんか?」と一言確認するだけでも、対策が入っているかどうかをその場で教えてもらえます。

まとめ

  • 保存ボタンを2回押すと、単純に2回リクエストが飛んで2件登録される
  • 原因は「送信中かどうか」を管理する状態がないこと
  • isSaving のような状態でボタンを無効化するだけで、多くの二重送信は防げる
  • 「連打されても大丈夫か」を、依頼の時点かレビューの時点で必ず確認する

未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md と学習モード(learner / developer)の設計までセットで含みます。

※ Qiita読者の方には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?