🍑
RTK Queryの活用: フックを使う場合と関数を使う場合の実装例
Redux ToolkitのRTK Queryには、フックを使う場合と関数をディスパッチする場合の2つのアプローチが存在する。
フックを使う場合: 状態管理が簡単で、コードがシンプルになり、コンポーネントで直接利用できる。
ディスパッチする場合: 高い柔軟性を持ち、コンポーネント外でも使用可能であり、複雑なロジックに対応しやすい。
なお、Redux Toolkitでの「スライス」は主に状態管理を担当する。一方、RTK Queryでの「スライス」はAPI呼び出しやキャッシング、ステータス管理を行う。混乱を避けるため、この記事ではRTK Queryの「スライス」を「APIエンドポイント」と呼ぶことにする。
1. フックを使う場合: カウンターのAPI管理の実装例
counterApi.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
// API定義
const counterApi = createApi({
reducerPath: 'counterApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }), //ベースURLを指定
endpoints: (builder) => ({ //エンドポイントを定義
//以下で、クエリとミューテーションを定義
getCounter: builder.query({
query: () => 'counter',
}),
incrementCounter: builder.mutation({
query: (amount) => ({
url: 'counter/increment',
method: 'POST',
body: { amount },
}),
}),
decrementCounter: builder.mutation({
query: (amount) => ({
url: 'counter/decrement',
method: 'POST',
body: { amount },
}),
}),
}),
});
//フックのエクスポート。これらのフックをコンポーネントで使用して、APIとのやり取りを行う
export const {
useGetCounterQuery,
useIncrementCounterMutation,
useDecrementCounterMutation
} = counterApi;
export default counterApi;
store.js
// ストアへのAPIエンドポイントの追加
import { configureStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query';
import countersReducer from './features/counters/countersSlice';
import counterApi from './counterApi'; // APIファイルをインポート
const store = configureStore({ //ストアを作成
// APIエンドポイントのリデューサーを追加
reducer: {
counters: countersReducer,
[counterApi.reducerPath]: counterApi.reducer,
},
// APIエンドポイントのミドルウェアを追加
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(counterApi.middleware),
});
//setupListenersを呼び出して、リアルタイム更新やポーリングを有効にする
setupListeners(store.dispatch);
export default store;
フックを使用してAPIからデータを取得する方法
CounterComponent.js
import React from 'react';
import {
useGetCounterQuery,
useIncrementCounterMutation,
useDecrementCounterMutation }
from './counterApi';
const CounterComponent = () => {
//useGetCounterQueryフックを使用してカウンターの値を取得する
const { data, error, isLoading } = useGetCounterQuery();
// フックを使用してカウンターの値を変更する
// フックは自動的にAPIリクエストを発行し、取得されたデータやリクエストのステータス
//(ロード中、成功、失敗など)がReduxストア内で管理される。
// このプロセスで、ストアの状態が変更されている
const [incrementCounter] = useIncrementCounterMutation();
const [decrementCounter] = useDecrementCounterMutation();
if (isLoading) {
return <div>Loading...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
<h1>Counter: {data?.value}</h1>
<button onClick={() => incrementCounter(1)}>Increment</button>
<button onClick={() => decrementCounter(1)}>Decrement</button>
</div>
);
};
export default CounterComponent;
2. 関数を使う場合: カウンターのAPI管理の実装例
counterApi.js
//... (上記のcounterApi.jsと同じ)
// フックの代わりに、APIエンドポイントを呼び出す関数を使用するためのエクスポート
export const {
getCounter,
incrementCounter,
decrementCounter
} = counterApi.endpoints;
export default counterApi;
store.js
// 上記のstore.jsと同じ。
関数を使用してAPIからデータを取得する方法
CounterComponent.js
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { counterApi } from './counterApi';
const CounterComponent = () => {
const dispatch = useDispatch();
useEffect(() => {
// useEffectを使って、コンポーネントがマウントされたときにデータを取得する
const fetchCounter = async () => {
const result = await
// dispatchを使用してAPIからデータを取得する
dispatch(counterApi.endpoints.getCounter.initiate());
};
fetchCounter();
}, [dispatch]);
const handleIncrement = async () => {
const result = await
// dispatchを使用してカウンターの値を変更する
// APIリクエストを行うための関数 (initiate) がdispatchされ、その結果は
// RTK Queryで処理され、データやステータスが自動的にReduxの状態に保存される
dispatch(counterApi.endpoints.incrementCounter.initiate(1));
};
const handleDecrement = async () => {
const result = await
// (同上)
dispatch(counterApi.endpoints.decrementCounter.initiate(1));
console.log(result.data);
};
return (
<div>
<h1>Counter Component</h1>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleDecrement}>Decrement</button>
</div>
);
};
export default CounterComponent;
Discussion