Reactとバックエンドで作る！実践Web開発入門 | 第6章: バックエンドにデータベースを追加

## はじめに
第5章でContext APIを使って状態を管理しました。今回は、バックエンドにデータベース（MongoDB）を追加し、商品データを永続的に保存します。これでアプリがより実践的になります。

## 目標
- MongoDBをバックエンドに統合する  
- APIをデータベースと連携させる  
- 商品の追加をサーバーに反映する  

## MongoDBの準備
1. **MongoDBのインストール**: 公式サイトからMongoDB Communityをダウンロードし、インストール。
2. **ローカルで起動**: ターミナルで`mongod`を実行（環境変数の設定が必要な場合あり）。
3. **MongoDB Atlas（代替案）**: ローカルが難しい場合、無料のクラウド版を利用可能。

## バックエンドのセットアップ
`backend`フォルダで以下の依存関係を追加：
```bash
npm install mongoose
```

## データベース接続とモデル作成
`backend/index.js`を以下のように更新：
```javascript
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const app = express();
const port = 5000;

app.use(express.json());
app.use(cors());

// MongoDBに接続
mongoose.connect('mongodb://localhost:27017/productdb', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
}).then(() => console.log('MongoDB connected'));

// 商品スキーマ
const productSchema = new mongoose.Schema({
  name: String,
  price: Number,
});

const Product = mongoose.model('Product', productSchema);

// APIエンドポイント
app.get('/products', async (req, res) => {
  const products = await Product.find();
  res.json(products);
});

app.post('/products', async (req, res) => {
  const { name, price } = req.body;
  const product = new Product({ name, price });
  await product.save();
  res.status(201).json(product);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});
```
- `mongoose`でMongoDBに接続。
- `Product`モデルを定義。
- `GET /products`で全商品を取得、`POST /products`で新商品を追加。

## 初期データの挿入（任意）
初回起動後、MongoDBにデータを手動で追加できます。MongoDBシェルで：
```bash
use productdb
db.products.insertMany([
  { name: "りんご", price: 100 },
  { name: "バナナ", price: 150 }
])
```

## React側の更新
`frontend/src/App.tsx`の`handleAddProduct`を修正し、バックエンドにPOSTリクエストを送信：
```tsx
const ProductList = () => {
  const { products, setProducts } = useProductContext();
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [newProduct, setNewProduct] = React.useState({ name: '', price: '' });

  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();
  }, [setProducts]);

  const handleAddProduct = async (e) => {
    e.preventDefault();
    if (newProduct.name && newProduct.price) {
      try {
        const response = await fetch('http://localhost:5000/products', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ name: newProduct.name, price: Number(newProduct.price) }),
        });
        if (!response.ok) throw new Error('商品の追加に失敗しました');
        const addedProduct = await response.json();
        setProducts((prev) => [...prev, addedProduct]);
        setNewProduct({ name: '', price: '' });
      } catch (err) {
        setError(err.message);
      }
    }
  };

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

  return (
    <main>
      <h2>商品一覧</h2>
      <form onSubmit={handleAddProduct}>
        <input
          type="text"
          placeholder="商品名"
          value={newProduct.name}
          onChange={(e) => setNewProduct({ ...newProduct, name: e.target.value })}
        />
        <input
          type="number"
          placeholder="価格"
          value={newProduct.price}
          onChange={(e) => setNewProduct({ ...newProduct, price: e.target.value })}
        />
        <button type="submit">追加</button>
      </form>
      <ul>
        {products.map((product) => (
          <ProductItem key={product._id} name={product.name} price={product.price} />
        ))}
      </ul>
    </main>
  );
};
```
- `POST`リクエストでバックエンドに商品を追加。
- 注意: MongoDBは`_id`を生成するので、`key={product._id}`に変更。

## 動作確認
1. MongoDBを起動。
2. バックエンドを起動（`node index.js`）。
3. フロントエンドを起動（`npm start`）。
4. `http://localhost:3000`で確認。商品を追加するとデータベースに保存され、リロードしても表示されます。

## 次回予告
第7章では、ユーザー認証を追加し、ログイン機能を実装します。お楽しみに！

---

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