🦔
Reactでフォームの多重送信を防ぐ
Reactでフォームの多重送信を防ぐ方法
問題
ボタンの押下処理実行中フラグをuseStateで管理していた場合、連打時に複数実行されてしまいフラグが正しく機能しなかった。
useStateは非同期更新のため、連打時に以下の問題が発生します:
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
event.stopPropagation();
if (isSubmitting) {
return;
}
setIsSubmitting(true); // 非同期で更新される
try {
const result = await submitForm(formData);
setIsSubmitting(false);
} catch (error) {
setIsSubmitting(false);
throw error;
}
};
// 連打時の問題:
// 1回目のクリック: isSubmitting = false → setIsSubmitting(true)(非同期)
// 2回目のクリック: isSubmitting = false(まだ更新されていない)→ 処理が実行される
解決方法
useRefに変更することで、連打時のフラグ管理が正しく動作するようになりました。
useRefは同期更新のため、即座に値が反映されます:
const isSubmittingRef = useRef<boolean>(false);
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
event.stopPropagation();
if (isSubmittingRef.current) {
return;
}
isSubmittingRef.current = true; // 即座に反映される
try {
const result = await submitForm(formData);
isSubmittingRef.current = false;
} catch (error) {
isSubmittingRef.current = false;
throw error;
}
};
// 連打時の解決:
// 1回目のクリック: isSubmittingRef.current = false → true(即座に反映)
// 2回目のクリック: isSubmittingRef.current = true → 早期リターン
ポイント
-
useState
→useRef
に変更 - 連打時のフラグ管理が正しく動作
- エラー時のみフラグをリセット
Discussion