Next.jsでAPIを作ろう
このページで学ぶこと
- Next.js の Route Handlers で API エンドポイントを作れる
- GET・POST リクエストを処理できる
- フロントエンドから自分で作った API を呼び出せる
Route Handlers とは
Next.js の App Router では、app/api/ フォルダに route.js を置くことで API を作れます。
app/
├── api/
│ └── todos/
│ └── route.js → GET /api/todos, POST /api/todos
└── page.jsやってみよう
ステップ1: GET エンドポイントを作る
app/api/todos/route.js を作成する。
// app/api/todos/route.js
import { NextResponse } from 'next/server'
// ダミーデータ(後でDBに置き換える)
const todos = [
{ id: 1, title: '牛乳を買う', completed: false },
{ id: 2, title: '洗濯する', completed: true },
{ id: 3, title: '課題を終わらせる', completed: false },
]
// GET /api/todos
export async function GET() {
return NextResponse.json(todos)
}ブラウザで http://localhost:3000/api/todos にアクセスすると、JSONが表示されます。
ステップ2: POST エンドポイントを追加する
// app/api/todos/route.js
import { NextResponse } from 'next/server'
let todos = [
{ id: 1, title: '牛乳を買う', completed: false },
{ id: 2, title: '洗濯する', completed: true },
]
// GET /api/todos
export async function GET() {
return NextResponse.json(todos)
}
// POST /api/todos
export async function POST(request) {
// リクエストボディをJSONとして読み込む
const body = await request.json()
// 簡単なバリデーション
if (!body.title) {
return NextResponse.json(
{ error: 'titleは必須です' },
{ status: 400 } // Bad Request
)
}
// 新しいTodoを作成
const newTodo = {
id: todos.length + 1,
title: body.title,
completed: false,
}
todos.push(newTodo)
return NextResponse.json(newTodo, { status: 201 }) // Created
}ステップ3: 特定IDのエンドポイントを作る
app/api/todos/[id]/route.js を作成する。
// app/api/todos/[id]/route.js
import { NextResponse } from 'next/server'
let todos = [
{ id: 1, title: '牛乳を買う', completed: false },
{ id: 2, title: '洗濯する', completed: true },
]
// GET /api/todos/:id
export async function GET(request, { params }) {
const id = parseInt(params.id)
const todo = todos.find((t) => t.id === id)
if (!todo) {
return NextResponse.json({ error: '見つかりません' }, { status: 404 })
}
return NextResponse.json(todo)
}
// DELETE /api/todos/:id
export async function DELETE(request, { params }) {
const id = parseInt(params.id)
todos = todos.filter((t) => t.id !== id)
return NextResponse.json({ message: '削除しました' })
}ステップ4: フロントエンドから呼び出す
app/page.js を書き換えて、自分で作った API を呼び出してみましょう。
// app/page.js
'use client'
import { useState, useEffect } from 'react'
export default function TodoApp() {
const [todos, setTodos] = useState([])
const [input, setInput] = useState('')
// 初回表示時にTodo一覧を取得
useEffect(() => {
fetch('/api/todos')
.then((res) => res.json())
.then((data) => setTodos(data))
}, [])
// Todoを追加する
const addTodo = async () => {
const res = await fetch('/api/todos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title: input }),
})
const newTodo = await res.json()
setTodos([...todos, newTodo])
setInput('')
}
return (
<div style={{ padding: '32px' }}>
<h1>Todoアプリ</h1>
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="新しいTodoを入力"
/>
<button onClick={addTodo}>追加</button>
</div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
)
}確認しよう
-
GET /api/todosでJSONが返ってくることをブラウザで確認した -
POST /api/todosでTodoを追加できた - フロントエンドから
fetchでAPIを呼び出せた - 400・404 のエラーレスポンスを返せた
AIに聞いてみよう
「Next.jsのRoute Handlersでミドルウェアを使って認証チェックをするにはどうしますか?」
次のステップ
Last updated on