ラベル Web開発 の投稿を表示しています。 すべての投稿を表示
ラベル Web開発 の投稿を表示しています。 すべての投稿を表示

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によるフォーム処理の実践 - 複数メールアドレスの処理

【第3回】フォームの作成とバリデーション(MUI + React Hook Form)

✅ はじめに

こんにちは!このシリーズでは、React + Vite + TypeScript + MUIという現代的な技術スタックを使って、Webアプリを開発する方法をステップバイステップで解説しています。

第3回となる今回は、フォームの作成とバリデーションを扱います。UIには MUI を、バリデーションには React Hook Form を使って、シンプルかつ堅牢なフォームを作成していきましょう。

📦 使用する技術スタック

ツール バージョン 説明
React Hook Form v7.x フォーム管理とバリデーション
MUI v5.x マテリアルデザインベースのUIコンポーネント
TypeScript 5.x 型安全なJavaScript
Vite 5.x 高速な開発環境とビルドツール

🚀 実装手順

1. プロジェクトの作成

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

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

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

MUIとReact Hook Formをインストールします:

npm install @mui/material @emotion/react @emotion/styled @fontsource/roboto react-hook-form

3. フォームコンポーネントの作成

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

import type { FC } from 'react';
import { useForm } from 'react-hook-form';
import { TextField, Button, Container, Typography, Paper } from '@mui/material';

type FormData = {
  name: string;
  email: string;
};

const UserForm: FC = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<FormData>();

  const onSubmit = (data: FormData): void => {
    alert(`名前: ${data.name}\nメール: ${data.email}`);
  };

  return (
    <Container maxWidth="sm">
      <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
        <Typography variant="h4" component="h1" gutterBottom>
          ユーザーフォーム
        </Typography>
        <form onSubmit={handleSubmit(onSubmit)} noValidate>
          <TextField
            fullWidth
            label="名前"
            margin="normal"
            {...register('name', { required: '名前は必須です' })}
            error={!!errors.name}
            helperText={errors.name?.message}
          />
          <TextField
            fullWidth
            label="メール"
            margin="normal"
            {...register('email', {
              required: 'メールは必須です',
              pattern: {
                value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
                message: '有効なメールアドレスを入力してください',
              },
            })}
            error={!!errors.email}
            helperText={errors.email?.message}
          />
          <Button 
            variant="contained" 
            type="submit" 
            sx={{ mt: 2 }}
            fullWidth
          >
            送信
          </Button>
        </form>
      </Paper>
    </Container>
  );
};

export default UserForm;

4. App.tsxの更新

最後に、src/App.tsxを更新してフォームを表示します:

import { ThemeProvider, createTheme } from '@mui/material';
import UserForm from './pages/UserForm';

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

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

export default App;

🎯 主要なポイント

1. React Hook Formの基本概念

  • useForm: フォームの状態管理とバリデーションを提供
  • register: フォームフィールドの登録とバリデーションルールの設定
  • handleSubmit: フォーム送信時の処理を管理
  • formState: エラー状態などのフォーム状態を管理

2. MUIフォームコンポーネント

  • TextField: 入力フィールドのスタイリングとエラー表示
  • Container: レスポンシブなレイアウト
  • Paper: カード風のコンテナスタイリング

3. TypeScriptの型安全性

  • FC型: Reactの関数コンポーネントの型定義
  • FormData型: フォームデータの型定義
  • 明示的な戻り値の型: 関数の戻り値型を指定

🔚 まとめ

今回は、React Hook FormとMUIを組み合わせて、型安全なバリデーション機能付きフォームを実装しました。この組み合わせは実用的で、多くの商用アプリでも採用されています。

📚 次回予告

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

2025年5月24日土曜日

【第2回】React Routerで画面遷移を実装しよう!

✅ はじめに

こんにちは!このシリーズでは、React + Vite + TypeScript + MUIという現代的な技術スタックを使って、Webアプリを開発する方法をステップバイステップで解説していきます。

第2回となる今回は、React Routerを使って「複数のページを持つアプリケーション」を作成します。画面遷移やルーティングの仕組みを理解することで、より本格的なアプリ開発ができるようになります!

📦 使用する技術スタック

ツール バージョン 説明
React Router v6.x Reactアプリケーションのルーティングライブラリ
MUI v5.x マテリアルデザインベースのUIコンポーネント
TypeScript 5.x 型安全なJavaScript
Vite 5.x 高速な開発環境とビルドツール

🚀 実装手順

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

npm install react-router-dom @mui/material @emotion/react @emotion/styled @fontsource/roboto

2. ページコンポーネントの作成

src/pages/Home.tsx

import { Container, Typography, Paper, Box } from '@mui/material';

const Home = () => {
  return (
    <Container maxWidth="md">
      <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
        <Typography variant="h4" component="h1" gutterBottom>
          ホームページ
        </Typography>
        <Box sx={{ mt: 2 }}>
          <Typography variant="body1">
            このアプリケーションは、React Router v6を使用した
            シンプルなルーティングのデモンストレーションです。
          </Typography>
        </Box>
      </Paper>
    </Container>
  );
};

export default Home;

src/pages/About.tsx

import { Container, Typography, Paper, Box, List, ListItem, ListItemText } from '@mui/material';

const About = () => {
  return (
    <Container maxWidth="md">
      <Paper elevation={3} sx={{ p: 4, mt: 4 }}>
        <Typography variant="h4" component="h1" gutterBottom>
          このアプリについて
        </Typography>
        <Box sx={{ mt: 2 }}>
          <Typography variant="body1" paragraph>
            このアプリケーションは以下の技術スタックを使用しています:
          </Typography>
          <List>
            <ListItem>
              <ListItemText 
                primary="React + TypeScript" 
                secondary="型安全なコンポーネント開発"
              />
            </ListItem>
            <ListItem>
              <ListItemText 
                primary="React Router v6" 
                secondary="モダンなルーティング機能"
              />
            </ListItem>
            <ListItem>
              <ListItemText 
                primary="Material-UI (MUI)" 
                secondary="美しいUIコンポーネント"
              />
            </ListItem>
          </List>
        </Box>
      </Paper>
    </Container>
  );
};

export default About;

3. App.tsxでのルーティング設定

import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import { 
  AppBar, 
  Toolbar, 
  Button, 
  Container, 
  ThemeProvider, 
  createTheme,
  Box,
  Typography
} from '@mui/material';
import Home from './pages/Home';
import About from './pages/About';

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

function App() {
  return (
    <ThemeProvider theme={theme}>
      <BrowserRouter>
        <Box sx={{ flexGrow: 1 }}>
          <AppBar position="static">
            <Toolbar>
              <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
                React Router Demo
              </Typography>
              <Button 
                color="inherit" 
                component={Link} 
                to="/"
                sx={{ mr: 2 }}
              >
                Home
              </Button>
              <Button 
                color="inherit" 
                component={Link} 
                to="/about"
              >
                About
              </Button>
            </Toolbar>
          </AppBar>
        </Box>

        <Container>
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
          </Routes>
        </Container>
      </BrowserRouter>
    </ThemeProvider>
  );
}

export default App;

🎯 主要なポイント

1. React Routerの基本概念

  • BrowserRouter: URLベースのルーティングを提供
  • Routes: ルート定義のコンテナ
  • Route: 個別のルートを定義
  • Link: ページ間のナビゲーション

2. MUIとの統合

  • AppBarによるナビゲーションバー
  • Containerによるレイアウト
  • Buttonコンポーネントとリンクの統合

3. 型安全性

  • TypeScriptによる型チェック
  • コンポーネントpropsの型定義

🔚 まとめ

このチュートリアルでは、React RouterとMUIを組み合わせて、モダンなナビゲーションを持つSPAを構築する方法を学びました。次回は、フォームの実装とバリデーションについて解説します。

📚 次回予告

【第3回】フォームの作成とバリデーション(MUI + React Hook Form)

【第1回】React + Vite + TypeScript + MUIで開発環境を最速構築しよう【2025年版】

✅はじめに

こんにちは!このシリーズでは、React + Vite + TypeScript + MUIという現代的な技術スタックを使って、Webアプリを開発する方法をステップバイステップで解説していきます。

第1回となる今回は、開発環境の構築と初期プロジェクトの作成、そしてMUIを使った簡単なUI表示までを行います。

📦使用する技術スタック

ツール バージョン 説明
React 19.1.0 フロントエンドJavaScriptライブラリ
Vite 6.3.5 爆速な開発環境を提供するビルドツール
TypeScript 5.8.3 型安全なJavaScriptのスーパーセット
MUI 7.1.0 Googleのマテリアルデザインに基づいたUIライブラリ

🛠1.必要なツールの準備

以下がインストールされていることを確認してください。

  • Node.js(最新版)
  • 任意のエディタ(例:Visual Studio Code)

🚀2.プロジェクトの作成

以下のコマンドをターミナルで実行して、Vite + React + TypeScript のプロジェクトを作成します。

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

🎨3.MUIのインストール

次に、MUIのライブラリとRobotoフォントをインストールします。

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

🧹4.index.cssを空にする

Vite のテンプレートには、初期状態でスタイルが含まれています。このスタイルは MUI のレイアウトに干渉するため、src/index.css の中身をすべて削除(もしくはコメントアウト)してください。

🧑‍💻5.main.tsxの編集

Robotoフォントを適用するために、src/main.tsxを以下のように編集します:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'

// Robotoフォントのインポート
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

👨‍💻6.App.tsxの作成

次に、src/App.tsxを以下のように書き換えて、MUIのコンポーネントとRobotoフォントを使用したUIを作成します:

import { useState } from 'react'
import { Button, Container, Typography, ThemeProvider, createTheme, Box } from '@mui/material'

type CounterProps = {
  initialCount?: number;
};

// カスタムテーマを作成
const theme = createTheme({
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
  },
});

function App({ initialCount = 0 }: CounterProps) {
  const [count, setCount] = useState(initialCount)

  return (
    <ThemeProvider theme={theme}>
      <Container maxWidth="sm" sx={{ textAlign: 'center', mt: 5 }}>
        <Typography variant="h4" gutterBottom>
          React + Vite + MUI スターター
        </Typography>
        <Typography variant="body1" gutterBottom>
          カウント: {count}
        </Typography>
        <Button variant="contained" onClick={() => setCount(count + 1)}>
          カウントを増やす
        </Button>

        {/* フォントの比較表示 */}
        <Box sx={{ mt: 4, display: 'flex', flexDirection: 'column', gap: 2 }}>
          <Typography variant="h6">
            フォントの比較
          </Typography>
          <Typography sx={{ fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif' }}>
            これはRobotoフォントです (The quick brown fox jumps over the lazy dog)
          </Typography>
          <Typography sx={{ fontFamily: 'system-ui, -apple-system, sans-serif' }}>
            これはシステムフォントです (The quick brown fox jumps over the lazy dog)
          </Typography>
        </Box>
      </Container>
    </ThemeProvider>
  )
}

export default App

✨主な変更点と改善点

  1. Robotoフォントの追加: MUIのデフォルトフォントであるRobotoを正しく実装
  2. ThemeProviderの導入: フォントファミリーを明示的に設定し、一貫したデザインを実現
  3. TypeScriptの活用: CounterPropsインターフェースを定義し、型安全性を確保
  4. フォント比較機能: Robotoフォントとシステムフォントの違いを視覚的に確認可能

✅表示確認

以下のコマンドで開発サーバーを起動しましょう。

npm run dev

ブラウザでhttp://localhost:5173を開くと、以下の要素が確認できます:

  • Robotoフォントを使用したヘッダーテキスト
  • カウンター機能付きのボタン
  • フォントの違いを確認できる比較セクション

🔚まとめ

これで、React + Vite + TypeScript + MUI の環境が整い、Robotoフォントも正しく実装されました!

📌次回予告

次回は、この環境を使って複数ページを作成する方法(React Router)を紹介します。お楽しみに!