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の使い方と注意点まとめにまとめています。