【React】 ボタンの多重クリックを防止する方法とは?

お問い合わせフォームで同じデータが登録されていて、
重複したデータがあるんだ。
間違って複数回クリックしたことが原因なんだけど、
ボタンを1回だけクリックできるようにできないかな?

確かにお問い合わせフォームなどでよく起こる問題だね!
同じデータが複数登録されるのは無駄なことで、
混乱も招いてしまうよね。
ちょっとしたテクニックを使うと簡単に解決できるよ!

目次

多重クリックによる問題とは?

多重クリックとはボタン操作などで発生したイベントが複数回実行され重複された処理になってしまうことです。

「2重クリック(送信)」、「2度押し」、「連打」、など呼び方は様々あります。

お問い合わせフォームの画面で「送信ボタン」を複数回クリックしてしまい、
同じ問い合わせ内容を複数回送ってしまったことはないでしょうか。

複数回処理が実行されることで、無駄なデータが増え、データ処理で予期しない問題が起こる可能性があります。

1回の送信を想定しているときは、多重クリックされないような処理にし、
多重クリックをされたとしても複数回処理が実行されないように制御する必要があります。

多重クリックを防止する方法

多重クリックを防止するためにはReactのHookである「useRef」を使います。

これは再レンダリングをしないという特徴を持っているためです。

useStateを使ってしまうとレンダリングの際に状態が変わってしまうことがあるためです。

それでは実際にソースコードで解説をしていきます。

import React, { useRef } from 'react';

export const PreventDuplicateClicks = () => {
  const submitProcessing = useRef(false); // ① 送信処理を管理するuseRefを作成する

  const submitForm = (event) => {
    event.preventDefault();
    event.stopPropagation();

    if(submitProcessing.current) return; // ② 送信処理中かを判定する(trueなら抜ける)
    submitProcessing.current = true; // ③ 送信処理中フラグを立てる

    // ④ 行いたい処理を記述する

    submitProcessing.current = false;  // ⑤ 送信処理中フラグを下げる
  };

  return (
    <form onSubmit={submitForm}>
      <button type="submit">送信する</button>
    </form>
  );
}
useRefを作成する

送信処理中かを判断するuseRefを作成します。

初期値はBoolean型で「false」とし、送信処理中ではないこととしておきます。

送信処理中かを判定する

送信処理に入ったらまずは送信処理中かどうかを判断します。

「treu」であれば送信処理中、「false」であれば送信処理はしていないことになります。

「false」であれば次の処理に進むようにします。

送信処理中フラグを立てる

送信処理を行う前に送信処理中か判断するuseRefの値を「true」とし、送信処理中であることを示します。

これで別の送信処理リクエストがあったとしても②の判定処理で別処理を防ぐことができます。

処理を行う

ここで行いたい処理を記述します。

同時に複数回実行されては困る処理など記述します。

ここに記述をすることで1クリックで1つの処理が実行させることができます。

送信処理中フラグを下げる

最後に送信処理中かを判断するフラグを「false」とし初期状態に戻すことで、
再度リクエスト処理を受け付けることができるようになります。

画面を更新するまで処理をさせたくないなど1回だけ処理を実行したいときは、
この処理はせずにそのままにしておきます。

コンポーネントが存在している間はuseRefが値を保ち続けるため、その値を変更しても再レンダリングが発生しません。

そのためuseRefは多重クリックを防止する際には相性が良く、再レンダリングによるパフォーマンス悪化や予期しない副作用を回避したいときも利用できます。

まとめ

  • 多重クリックの防止処理にはuseRefを使う
  • 送信処理中フラグをtureやfalseにすることで多重クリックを回避することができる

多重クリックを防止するときはuseRefを使って処理をしていくよ!

useRefってこんな使い方もできるんだね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次