Todoアプリ - 連携編
いよいよ最終ステップ!フロントエンドとバックエンドを連携させて、完全なTodoアプリを完成させます。
連携の流れ
Next.js
localhost:3000
⇄ fetch API ⇄
FastAPI
localhost:8000
Step 1: API通信関数を作成
AIへの指示
frontend/src/lib/api.ts を作成して、
TodoのAPI通信関数を作成してください。
関数:
- fetchTodos(): 全Todo取得
- createTodo(title: string): Todo作成
- updateTodo(id: number, data: { completed?: boolean }): Todo更新
- deleteTodo(id: number): Todo削除
APIのベースURL: http://localhost:8000
完成コード例: src/lib/api.ts
import { Todo } from "@/types/todo"; const API_URL = "http://localhost:8000"; export async function fetchTodos(): Promise<Todo[]> { const res = await fetch(`${API_URL}/todos`); return res.json(); } export async function createTodo(title: string): Promise<Todo> { const res = await fetch(`${API_URL}/todos`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title }), }); return res.json(); } export async function updateTodo( id: number, data: { title?: string; completed?: boolean } ): Promise<Todo> { const res = await fetch(`${API_URL}/todos/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), }); return res.json(); } export async function deleteTodo(id: number): Promise<void> { await fetch(`${API_URL}/todos/${id}`, { method: "DELETE", }); }
Step 2: ページをAPI連携に変更
AIへの指示
frontend/src/app/page.tsx を編集して、 モックデータの代わりにAPIを使うように変更してください。 変更内容: 1. useEffectで初回読み込み時にfetchTodosを呼ぶ 2. addTodo関数をcreateToを使うように変更 3. toggleTodo関数をupdateTodoを使うように変更 4. deleteTodo関数をdeleteTodoAPIを使うように変更 5. ローディング状態を追加(読み込み中は「Loading...」を表示)
主要な変更点
"use client"; import { useState, useEffect } from "react"; import { Todo } from "@/types/todo"; import * as api from "@/lib/api"; export default function Home() { const [todos, setTodos] = useState<Todo[]>([]); const [newTitle, setNewTitle] = useState(""); const [loading, setLoading] = useState(true); // 初回読み込み useEffect(() => { api.fetchTodos().then((data) => { setTodos(data); setLoading(false); }); }, []); // Todo追加 const addTodo = async () => { if (!newTitle.trim()) return; const newTodo = await api.createTodo(newTitle); setTodos([...todos, newTodo]); setNewTitle(""); }; // 完了切り替え const toggleTodo = async (id: number, completed: boolean) => { const updated = await api.updateTodo(id, { completed: !completed }); setTodos(todos.map(t => t.id === id ? updated : t)); }; // 削除 const handleDelete = async (id: number) => { await api.deleteTodo(id); setTodos(todos.filter(t => t.id !== id)); }; if (loading) return <div>Loading...</div>; // ... 以下、表示部分は同じ }
Step 3: 動作確認
両方のサーバーを起動
ターミナル1(バックエンド)
cd backend uvicorn main:app --reload
ターミナル2(フロントエンド)
cd frontend npm run dev
確認項目
- ページを開くとバックエンドのデータが表示される
- 新しいTodoを追加すると、バックエンドにも保存される
- 完了状態を切り替えると、バックエンドも更新される
- 削除すると、バックエンドからも削除される
- ページをリロードしてもデータが残っている!
Todoアプリ完成!
おめでとうございます!Next.js + FastAPIのフルスタックアプリが完成しました!
よくあるエラーと解決法
CORSエラー
ブラウザのコンソールに「CORS」と表示される
解決法:FastAPIのCORS設定でhttp://localhost:3000を許可しているか確認
データが表示されない
Loading...のまま、またはエラー
解決法:バックエンドサーバーが起動しているか確認。http://localhost:8000/docsにアクセスできるか確認
追加/更新/削除が反映されない
操作してもリストが変わらない
解決法:API関数でawaitを忘れていないか確認。ブラウザのコンソールでエラーを確認
第3部完了!
チュートリアルお疲れさまでした!Next.js + FastAPIでフルスタックアプリを作る流れを体験できました。