Reactとバックエンドで作る！実践Web開発入門 | 第4章: Reactとバックエンドを連携

## はじめに
第3章でバックエンドにAPIを作成しました。今回は、ReactからそのAPIを呼び出し、商品リストを動的に表示します。データの取得やエラー処理の基本も学びます。

## 目標
- ReactでAPIを呼び出す方法を学ぶ  
- バックエンドから取得したデータを表示する  
- ローディング状態とエラー処理を実装する  

## API呼び出しの準備
ReactでAPIを呼び出すには、`fetch`または`axios`を使います。今回はシンプルな`fetch`を使用します。必要に応じて、`axios`をインストールすることもできます：
```bash
npm install axios
```

## ProductListコンポーネントの更新
`frontend/src/App.tsx`の`ProductList`を以下のように修正します：
```tsx
import React, { useEffect, useState } from 'react';

const ProductList = () => {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchProducts = async () => {
      try {
        const response = await fetch('http://localhost:5000/products');
        if (!response.ok) throw new Error('データの取得に失敗しました');
        const data = await response.json();
        setProducts(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchProducts();
  }, []);

  if (loading) return <main>読み込み中...</main>;
  if (error) return <main>エラー: {error}</main>;

  return (
    <main>
      <h2>商品一覧</h2>
      <ul>
        {products.map((product) => (
          <ProductItem key={product.id} name={product.name} price={product.price} />
        ))}
      </ul>
    </main>
  );
};

const ProductItem = ({ name, price }) => (
  <li>
    {name} - {price}円
  </li>
);
```
- `useState`で状態（商品、ローディング、エラー）を管理。
- `useEffect`でページ読み込み時にAPIを呼び出し。
- `fetch`でバックエンドからデータを取得。

## 全体のコード
`App.tsx`全体は以下のようになります：
```tsx
import React, { useEffect, useState } from 'react';
import './App.css';

function App() {
  return (
    <div className="App">
      <Header />
      <ProductList />
      <Footer />
    </div>
  );
}

const Header = () => (
  <header>
    <h1>商品リスト</h1>
  </header>
);

const ProductList = () => {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchProducts = async () => {
      try {
        const response = await fetch('http://localhost:5000/products');
        if (!response.ok) throw new Error('データの取得に失敗しました');
        const data = await response.json();
        setProducts(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchProducts();
  }, []);

  if (loading) return <main>読み込み中...</main>;
  if (error) return <main>エラー: {error}</main>;

  return (
    <main>
      <h2>商品一覧</h2>
      <ul>
        {products.map((product) => (
          <ProductItem key={product.id} name={product.name} price={product.price} />
        ))}
      </ul>
    </main>
  );
};

const ProductItem = ({ name, price }) => (
  <li>
    {name} - {price}円
  </li>
);

const Footer = () => (
  <footer>
    <p>© 2025 React Web開発入門</p>
  </footer>
);

export default App;
```

## 動作確認
1. バックエンドを起動（`backend`で`node index.js`）。
2. フロントエンドを起動（`frontend`で`npm start`）。
3. `http://localhost:3000`で確認。商品リストが表示されれば成功です。

## 注意点
- バックエンドが起動していない場合、エラーメッセージが表示されます。
- CORSが正しく設定されていることを確認してください（第3章参照）。

## 次回予告
第5章では、Reactの状態管理を強化し、Context APIやReduxの基本を学びます。お楽しみに！

---

この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします！質問や感想はコメント欄で気軽にどうぞ。次回も一緒に学びましょう！