React

【React】Reduxでクリックしたら複数のdispatchを実行する方法

ReactとReduxでボタンをクリックしたときに複数のdispatchを実行する方法を紹介します。onClickに波括弧つきの関数を渡すだけで順番に実行でき、Redux Toolkit・非同期・TypeScriptの書き方も合わせて解説します。

この記事の目次
  1. ReactでReduxでクリックしたら複数のdispatchを実行する方法
  2. Redux Toolkit(RTK)が使える場合
  3. 非同期処理がある場合
  4. TypeScript対応

ReactでReduxでクリックしたら複数のdispatchを実行する方法を紹介します。

結論から言うと、onClickのアロー関数を() => { dispatch(A()); dispatch(B()); }のように波括弧つきで書き、dispatchを続けて呼ぶだけです。
dispatchは同期的に順番に実行され、React 18以降では複数のdispatchによる再レンダリングは自動でまとめられる(バッチ処理)ため、画面が2回描画される心配もありません。

ReactでReduxでクリックしたら複数のdispatchを実行する方法

import { useDispatch, useSelector } from 'react-redux';

// useDispatchを使用してdispatch関数を取得
const dispatch = useDispatch();

useDispatchを使うことで、Reduxのdispatch関数をReactコンポーネントで利用できます。また、useSelectorを使えば、Reduxストアの状態を取得できます。
useDispatchはフックなので、コンポーネントのトップレベルで呼び出し、イベントハンドラーの中では呼び出しません。

          <button
            type="button"
            onClick={() => dispatch(closeModal())}
          >
            ボタン
          </button>

通常は上のように書くと一つだけ実行されます。

複数実行する場合は、clickのfunction部分を省略せずに書けばOKです。

          <button
            type="button"
            onClick={() => {
              dispatch(clearCart());
              dispatch(closeModal());
            }}
          >
            ボタン
          </button>

もしくは、関数を変数に入れて、それをonClickに登録すればOKです。

const handleClick = () => {
  dispatch(clearCart());
  dispatch(closeModal());
};

<button type="button" onClick={handleClick}>
  ボタン
</button>

よくある間違いは、onClick={dispatch(closeModal())}のように関数の呼び出し結果を渡してしまうことです。
この書き方だとレンダリングのたびにdispatchが実行され、クリック時には何も起きません。
onClickには必ず「関数そのもの」を渡します。

スポンサーリンク

Redux Toolkit(RTK)が使える場合

Redux Toolkit(RTK)は現在、Reduxの標準的な推奨ツールです。Redux Toolkitを使えば、より簡潔にdispatchやstate管理を行えます。
createSliceで作ったアクションクリエイター(clearCart、closeModalなど)をimportして、同じようにdispatchに渡します。

import { clearCart, closeModal } from './features/cartSlice';

<button
  type="button"
  onClick={() => {
    dispatch(clearCart());
    dispatch(closeModal());
  }}
>
  ボタン
</button>;

現在では、Redux Toolkitを使用することでdispatchやactionの管理が簡潔になり、可読性や開発効率が向上します。

非同期処理がある場合

複数のdispatchを実行するケースでは、非同期処理を伴うこともあります。Redux ThunkやRTK Queryなどのミドルウェアを使った非同期処理の例を紹介します。

const handleClick = async () => {
  await dispatch(fetchData());
  dispatch(closeModal());
};

<button type="button" onClick={handleClick}>
  ボタン
</button>;

非同期処理を伴う場合は、Redux Thunkなどのミドルウェアを使うことで、より効率的にdispatchを制御できます。
Redux ToolkitのcreateAsyncThunkで作ったアクションは、上のようにdispatchの戻り値をawaitできるため、「取得が終わってからモーダルを閉じる」といった順序の制御が書けます。

TypeScript対応

React 19とReduxを使うプロジェクトでは、TypeScriptを利用するケースが増えています。TypeScript対応について簡単に触れます。

import { useDispatch } from 'react-redux';
import type { AppDispatch } from './store';

const Sample = () => {
  // フックはコンポーネントのトップレベルで呼ぶ
  const dispatch = useDispatch<AppDispatch>();

  const handleClick = () => {
    dispatch(clearCart());
    dispatch(closeModal());
  };

  return (
    <button type="button" onClick={handleClick}>
      ボタン
    </button>
  );
};

Redux ToolkitはTypeScript対応が強化されており、型安全なdispatchやstate管理が可能です。
AppDispatchはtypeof store.dispatchでstore側に定義しておきます。
公式ドキュメントでは、useDispatch.withTypes<AppDispatch>()で型付きのフックを作っておく方法も推奨されています。

Reduxそのものの流れ(Store・Action・Reducer)をおさらいしたい場合はReduxの仕組みを1分で理解する、そもそもReduxが必要かを判断したい場合はReduxとは?Reactで使う意味・不要なケースを参考にしてみてください。
Reduxを使わず、useStateだけで同じことをする場合の注意点はuseStateの使い方と注意点まとめにまとめています。

スポンサーリンク