検索ボックスの入力ごとにAPIを呼ぶと、表示が一瞬前の結果に戻ることがある
検索ボックスに文字を打つたびに、その都度APIを呼んで候補を表示する実装があります。1文字打つごとにサーバーに問い合わせる、よくある作りです。この実装、AIに頼んでそのまま動かしていると、稀に「消したはずの古い検索結果が一瞬だけ画面に戻る」という不具合が起きることがあります。
起きていること
(useEffect の依存配列の付け方や、無限ループになるかどうかの話ではありません。ここで扱うのは、複数回発火したリクエストが「どの順番で画面に届くか」という話です。)
「a」と打つと1回目のリクエストが飛び、続けて「ap」と打つと2回目、「app」まで打つと3回目のリクエストが飛びます。ここで多くの人が無意識に前提にしているのが、「一番最後に投げたリクエストの結果が、一番最後に画面に反映されるはず」という順序です。
実際には、ネットワークの応答はリクエストを投げた順番どおりに返ってくるとは限りません。3回目の「app」の結果より先に届くはずの2回目の「ap」の結果が、サーバー側の混雑や処理時間の差で3回目より遅れて届くことがあります。すると、先に届いた「app」の正しい結果を、後から届いた「ap」の古い結果が上書きしてしまいます。画面には一瞬、消したはずの古い検索結果が表示されます。
対処1: クリーンアップ関数で「もう古い」と印を付ける
useEffect のクリーンアップ関数を使い、「このリクエストの結果はもう使わない」と印を付ける方法があります。
useEffect(() => {
let ignore = false;
fetch(`/api/search?q=${query}`)
.then((res) => res.json())
.then((data) => {
if (!ignore) {
setResults(data);
}
});
return () => {
ignore = true;
};
}, [query]);
query が変わるたびにこの useEffect が再実行されますが、直前の実行で登録したクリーンアップ関数(ignore = true にする部分)が先に呼ばれます。古いリクエストの結果が届いても、ignore が true になっているので setResults は実行されません。結果が届く順番に関係なく、常に一番最後に打った文字に対応する結果だけが画面に反映されます。
対処2: AbortControllerで前のリクエスト自体を打ち切る
もう1つの方法は、新しいリクエストを送る前に、直前のリクエストそのものをキャンセルすることです。
useEffect(() => {
const controller = new AbortController();
fetch(`/api/search?q=${query}`, { signal: controller.signal })
.then((res) => res.json())
.then((data) => setResults(data))
.catch((err) => {
if (err.name !== "AbortError") {
console.error(err);
}
});
return () => {
controller.abort();
};
}, [query]);
ignore フラグとの違いは、リクエスト自体を打ち切るので、サーバー側やネットワーク上の無駄な通信を減らせる点です。ユーザーが素早く何文字も打ち込む検索ボックスのような場面では、こちらの方が無駄が少なくなります。
AIに実装を頼むときに一言添えると変わること
「検索ボックスを作って、入力するたびに候補をAPIから取得して」とだけ頼むと、多くの場合はリクエストを送る部分だけが実装され、この順序のずれは考慮されません。動作確認でも、よほど意識してタイミングをずらさない限り再現しにくいため、見た目には「動いている」ように見えてしまいます。
依頼する際に「古いリクエストの結果が、後から届いた新しい結果を上書きしないようにしてほしい」と一言添えておくと、ignore フラグや AbortController を使った実装を最初から提案してもらいやすくなります。動いているように見えるコードと、こうした細かい前提まで踏まえたコードの違いを見分けられるようになると、AIの実装をそのまま受け取るだけでなく、状況に応じてどこまで頼むかを自分で判断できるようになります。
面談なしで、今日から始められます
この講座は 未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を全24セッションで体系化した教材付きプランです。無料相談を挟まず、申し込んだその日から教材で学習を始められます。AIが学習パートナーになって何度でも質問でき、つまずいた所だけチャットで直接サポートします。
- 今日から始める(教材完全版+月5,500円・チャット質問し放題・いつでも解約OK)→ https://menta.work/plan/20251?ref=menta-knowledge
- いきなりは不安な方へ:無料の教材体験版もあります(最初の数セッション分)→ プラン詳細をご覧ください

