2025年5月25日日曜日

【第4回】状態管理とAPI通信(React + Axios)

✅ はじめに

こんにちは!このシリーズでは、React + Vite + TypeScript + MUIを使ってモダンなWebアプリを開発する方法をステップバイステップで解説しています。

第4回となる今回は、「外部APIとの通信(Axios)」と「状態管理(useState, useEffect)」を学びます。APIから取得したデータを画面に表示する実践的な構成です。

📦 使用する技術スタック

ツール バージョン 説明
Axios v1.x HTTP通信を行う人気のライブラリ
MUI v5.x マテリアルデザインベースのUIコンポーネント
TypeScript 5.x 型安全なJavaScript
Vite 5.x 高速な開発環境とビルドツール

🚀 実装手順

1. プロジェクトの作成

まずは、Viteを使って新しいプロジェクトを作成します:

npm create vite@latest react-api-app -- --template react-ts
cd react-api-app
npm install

2. 必要なパッケージのインストール

MUIとAxiosをインストールします:

npm install @mui/material @emotion/react @emotion/styled @fontsource/roboto axios

3. ユーザー一覧コンポーネントの作成

src/pages/UserList.tsxを作成します:

import type { FC } from 'react';
import { useEffect, useState } from 'react';
import type { AxiosResponse } from 'axios';
import axios from 'axios';
import {
  Container,
  Typography,
  List,
  ListItem,
  ListItemText,
  CircularProgress,
  Alert,
  Paper
} from '@mui/material';

type User = {
  id: number;
  name: string;
  email: string;
};

const UserList: FC = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');

  useEffect(() => {
    axios.get<User[]>('https://jsonplaceholder.typicode.com/users')
      .then((res: AxiosResponse<User[]>) => {
        setUsers(res.data);
        setLoading(false);
      })
      .catch(() => {
        setError('ユーザーの取得に失敗しました。');
        setLoading(false);
      });
  }, []);

  if (loading) {
    return (
      <Container maxWidth="sm">
        <Paper elevation={3} sx={{ p: 4, mt: 4, textAlign: 'center' }}>
          <CircularProgress />
        </Paper>
      </Container>
    );
  }

  if (error) {
    return (
      <Container maxWidth="sm">
        <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
          <Alert severity="error">{error}</Alert>
        </Paper>
      </Container>
    );
  }

  return (
    <Container maxWidth="sm">
      <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
        <Typography variant="h4" component="h1" gutterBottom>
          ユーザー一覧
        </Typography>
        <List>
          {users.map(user => (
            <ListItem key={user.id} divider>
              <ListItemText 
                primary={user.name} 
                secondary={user.email}
              />
            </ListItem>
          ))}
        </List>
      </Paper>
    </Container>
  );
};

export default UserList;

4. App.tsxの更新

最後に、src/App.tsxを更新してユーザー一覧を表示します:

import { ThemeProvider, createTheme } from '@mui/material';
import UserList from './pages/UserList';
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';

const theme = createTheme({
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>
      <UserList />
    </ThemeProvider>
  );
}

export default App;

🎯 主要なポイント

1. 状態管理

  • useState: データ、ローディング、エラー状態の管理
  • useEffect: コンポーネントマウント時のAPI呼び出し
  • 型安全な状態管理: TypeScriptによる型定義

2. API通信

  • Axios: 型安全なHTTPクライアント
  • エラーハンドリング: try-catchによる例外処理
  • ローディング表示: ユーザー体験の向上

3. UIコンポーネント

  • List/ListItem: データの一覧表示
  • CircularProgress: ローディング表示
  • Alert: エラーメッセージの表示

🔚 まとめ

今回は、Reactで外部APIからデータを取得し、それを状態として管理して表示する方法を学びました。MUIとAxiosを組み合わせることで、実用的な画面が簡単に作成できることが実感できたと思います。

📚 次回予告

【第5回】React Hook Formによるフォーム処理の実践 - 複数メールアドレスの処理