🦔

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 → 早期リターン

ポイント

  • useStateuseRefに変更
  • 連打時のフラグ管理が正しく動作
  • エラー時のみフラグをリセット
ランサーズ株式会社

Discussion