Reduxで外部APIからのデータを取得して初期状態に設定する方法

# はじめに
私は、働く人が働きやすく、企業は働きやすいから人が育ち、より良いサービスを提供できるから多くの人が喜べる。と考えております。
このサイクルで大きな一助になれるのは、エンジニアの力。企業発展や働く人がより輝けるWEBサービスを提供できるエンジニアを目指し、1年ほど前から独学を始め、現在はAPPRENTICE3期生として学ばせていただいております。
APPRENTICEについて

## Reduxで外部APIからのデータを取得して初期状態に設定する方法

Reduxは、アプリケーションの状態管理を効率化するためのライブラリです。しかし、外部APIからデータを取得して初期状態に設定する場合、非同期処理を扱う必要があります。この記事では、Redux Thunkを使ってこれを実現する方法をステップバイステップで説明します。

## 使用環境
MacBook Pro : M1 チップ / 16 GB
Next.js : 14.2.2
React : 18
Redux : 9.1.2
Redux Toolkit : 2.2.3

## 1. 外部APIから取得するデータの型定義を行う

まず、APIから取得するデータの型を定義します。TypeScriptを使用する場合、これによりコードの可読性と保守性が向上します。

```typescript
export interface ActionData {
  id?: number;
  name?: string;
  isCompleted?: number;
}

export interface SkillData {
  [skill: string]: {
    id?: number;
    actions: ActionData[];
  };
}

export type ChartData = {
  id: number;
  userName: string;
  userImage: string;
  userEmail: string;
  reachName: string;
  skills: SkillData;
  actionCount?: number;
  executedActionCount?: number;
  days: number;
  createdAt: string;
};
```

## 2. 非同期アクションの作成
次に、非同期処理を行う関数を作成します。この関数はcreateAsyncThunkを使用して定義します。
```typescript

import { createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';

export const fetchAuthChartData = createAsyncThunk<ChartData[], { authEmail: string }>(
  'authChart/fetchAuthChartData',
  async ({ authEmail }) => {
    const res = await axios.post('http://localhost:3000/api/myChart', { authEmail });
    const data = await res.data;
    return data;
  }
);
```

## 3. SliceファイルのextraReducersで非同期処理を管理する
次に、Sliceファイルで非同期処理の段階的な処理を定義します。

```typescript

import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { fetchAuthChartData } from './fetchAuthChartData';

const initialState = {
  authChartDatas: [] as ChartData[],
  loading: false,
  error: null as string | null,
};

const authChartsSlice = createSlice({
  name: 'authChart',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchAuthChartData.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchAuthChartData.fulfilled, (state, action: PayloadAction<ChartData[]>) => {
        state.authChartDatas = action.payload;
        state.loading = false;
      })
      .addCase(fetchAuthChartData.rejected, (state) => {
        state.loading = false;
        state.error = "Failed to fetch data";
      });
  },
});

export default authChartsSlice.reducer;
```
## 4. SliceファイルをStoreに登録する
次に、このSliceファイルをRedux Storeに登録します。

```typescript
// store.ts
import { configureStore } from '@reduxjs/toolkit';
import authChartReducer from './slice/AuthChartsSlice';

const store = configureStore({
  reducer: {
    authChart: authChartReducer,
    // 他のリデューサーを必要に応じて追加
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export default store;
```
## 5. コンポーネントで非同期処理を実行する
最後に、コンポーネントで非同期処理を実行し、取得したデータを表示します。

```typescript
"use client";

import { useAppDispatch, useAppSelector } from "@/store/hooks";
import { useEffect } from "react";
import { useSession } from "next-auth/react";
import { fetchAuthChartData, ChartData } from "@/store/slice/AuthChartsSlice";
import ChartIndex from "../features/chartView/Index";

export default function MyChart() {
  const { data: session } = useSession();
  const authEmail = session?.user?.email || '';

  const dispatch = useAppDispatch();

  useEffect(() => {
    if (authEmail) {
      dispatch(fetchAuthChartData({ authEmail }));
    }
  }, [dispatch, authEmail]);

  const { authChartDatas, loading, error } = useAppSelector((state) => state.authChart);

  return (
    <div>
      {loading && <p>Loading...</p>}
      {error && <p>{error}</p>}
      {authChartDatas &&
        authChartDatas.map((authChartData: ChartData) => (
          <ChartIndex key={authChartData.id} chartData={authChartData} />
        ))
      }
    </div>
  );
}
``` 

これで、外部APIから取得したデータをReduxの状態に設定し、コンポーネントで表示する方法が完成しました。Redux Thunkを使用することで、非同期処理をシンプルかつ効率的に管理できます。ぜひ、試してみてください。