2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Posted at

はじめに

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

目標

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

MongoDBの準備

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

バックエンドのセットアップ

backendフォルダで以下の依存関係を追加:

npm install mongoose

データベース接続とモデル作成

backend/index.jsを以下のように更新:

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シェルで:

use productdb
db.products.insertMany([
  { name: "りんご", price: 100 },
  { name: "バナナ", price: 150 }
])

React側の更新

frontend/src/App.tsxhandleAddProductを修正し、バックエンドにPOSTリクエストを送信:

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章では、ユーザー認証を追加し、ログイン機能を実装します。お楽しみに!


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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?