🐦

Button の disabled だけで安心してはいけない

に公開

disabledだけで安心していませんか?Reactでのボタン制御に潜む落とし穴

はじめに

Reactでボタンを一時的に無効化するには、disabled属性を使うのが定番です。
例えば、送信中に二重クリックを防ぐための実装は次のようになります。

<button disabled={isSubmitting}>送信</button>

一見するとこれで十分に思えるかもしれません。
しかし、実はこの実装だけでは不十分なケースもあるのです。


disabledは見た目だけの制御

disabled属性を設定すれば、確かにUI上ではボタンが押せなくなります。
しかしこれはあくまでフロント側の見た目の制御にすぎません。

たとえば、ブラウザの開発者ツールを使えば、disabled属性は簡単に解除できてしまいます。

document.querySelector('button')!.disabled = false;

このように、ユーザーが無効化されたはずのボタンを操作できてしまう可能性があるため、UIの制御だけでは不十分です。


より安全なフロントエンド実装

Reactでは、見た目の制御(disabled)に加えて、処理の実行自体を制御するロジックを組み込むことで、より安全な実装が可能になります。

以下はその一例です。

import { useState } from "react";

export const SubmitButton: React.FC = () => {
  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleClick = async () => {
    if (isSubmitting) return; // 二重実行防止

    setIsSubmitting(true);

    try {
      // 疑似的な非同期処理
      await fakeApiRequest();
      alert("送信完了");
    } catch (error) {
      console.error("送信エラー", error);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <button onClick={handleClick} disabled={isSubmitting}>
      {isSubmitting ? "送信中..." : "送信"}
    </button>
  );
};

const fakeApiRequest = (): Promise<void> => {
  return new Promise((resolve) => setTimeout(resolve, 2000));
};

実装のポイント

  • isSubmitting による状態管理
  • handleClick 内での早期リターン(if (isSubmitting) return
  • disabled 属性と連動させたUI制御

これにより、UIだけでなく処理の実行そのものを制御できるため、ユーザーによる操作や意図しない挙動をより確実に防げます。


おわりに

disabled属性は便利ですが、それだけに頼るのは危険です。
Reactのようなフレームワークでは、UIとロジックを連携させることで、より堅牢なインターフェースが構築できます。

ボタン一つの挙動にも、セキュリティやユーザー体験への配慮が求められる時代です。
ぜひ一度、自身のコードを見直してみてください。

Discussion