はじめに
第5章でContext APIを使って状態を管理しました。今回は、バックエンドにデータベース(MongoDB)を追加し、商品データを永続的に保存します。これでアプリがより実践的になります。
目標
- MongoDBをバックエンドに統合する
- APIをデータベースと連携させる
- 商品の追加をサーバーに反映する
MongoDBの準備
- MongoDBのインストール: 公式サイトからMongoDB Communityをダウンロードし、インストール。
-
ローカルで起動: ターミナルで
mongod
を実行(環境変数の設定が必要な場合あり)。 - 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.tsx
のhandleAddProduct
を修正し、バックエンドに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}
に変更。
動作確認
- MongoDBを起動。
- バックエンドを起動(
node index.js
)。 - フロントエンドを起動(
npm start
)。 -
http://localhost:3000
で確認。商品を追加するとデータベースに保存され、リロードしても表示されます。
次回予告
第7章では、ユーザー認証を追加し、ログイン機能を実装します。お楽しみに!
この記事が役に立ったら、ぜひ「いいね」や「ストック」をお願いします!質問や感想はコメント欄で気軽にどうぞ。次回も一緒に学びましょう!