0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js + Prismaで作成したTodoアプリのデバッグ: 予期しないAPIレスポンスの処理

Last updated at Posted at 2025-01-21

はじめに

Next.jsとPrismaを使用してTodoアプリを作成し、Vercelにデプロイした際に遭遇したエラーとその解決方法について共有する。この記事は、地震の備忘録とすること、また同様の問題に直面している開発者の助けになることを目的としている。

問題

デプロイ後、タスクのチェックボックスをクリックすると、タスクの表示が消えてエラーが発生した。エラーの内容は以下の通り:
[Each child in a list should have a unique "key" prop.]

原因

デバッグの結果、以下の問題が明らかになった:

  1. APIレスポンスに予期しないデータ({count: 1})が含まれていた
  2. フロントエンドでのAPIレスポンスの処理が不適切だった
  3. エラーハンドリングが不十分だった
  4. 更新操作後のデータ管理が適切でなかった

解決方法

1. APIレスポンスの修正

app/api/user-todos/route.tsファイルを以下のように修正しました:

export async function PUT(request: Request) {
  try {
    const userId = await getUserId(request)
    const { id, title, completed } = await request.json()
    await prisma.userTodo.updateMany({
      where: { id, userId },
      data: { title, completed },
    })
    //return NextResponse.json(userTodo); //削除
    // 更新後のTodoを返す
    const updatedTodo = await prisma.userTodo.findUnique({ where: { id } })
    return NextResponse.json(updatedTodo)
  } catch (error) {
    return NextResponse.json({ error: 'Not authenticated' }, { status: 401 })
  }
}

const fetchUserTodos = async () => {
  try {
    const response = await fetch('/api/user-todos', {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    const data = await response.json()
    if (Array.isArray(data)) {
      setUserTodos(data)
    } else {
      console.error('Unexpected API response:', data)
      setUserTodos([])
    }
  } catch (error) {
    console.error('Error fetching todos:', error)
    setUserTodos([])
  }
}

2. フロントエンドでのデータ処理の改善

app/page.tsxファイルを以下のように修正した:


const toggleUserTodo = async (id: string) => {
  const userTodo = userTodos.find(t => t.id === id)
  if (!userTodo) return
  try {
    const response = await fetch('/api/user-todos', {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      },
      body: JSON.stringify({ ...userTodo, completed: !userTodo.completed }),
    })
    const updatedTodo = await response.json()
    if (updatedTodo && updatedTodo.id) {
      setUserTodos(userTodos.map(t => t.id === id ? updatedTodo : t))
    } else {
      console.error('Unexpected API response:', updatedTodo)
    }
  } catch (error) {
    console.error('Error updating todo:', error)
  }
}

結論

実現した改善点

これらの修正により、以下の改善が実現した:

  1. APIレスポンスの適切な検証
  2. エラーハンドリングの強化
  3. 更新操作後の適切なデータ管理
  4. 予期しないデータの除外

得られた教訓

この経験から、以下の重要な教訓を得た:

  • APIレスポンスの形式を常に検証する
    • 予期しないデータ構造に対して堅牢なコードを書く
  • 適切なエラーハンドリングを行う
    • ユーザー体験を損なわないよう、エラーを適切に処理する
  • サーバー側とクライアント側のデータの一貫性を保つ
    • 更新操作後は最新のデータを取得し、状態を同期させる
  • 予期しないデータやエラーに対して、適切なフォールバック処理を実装する
    • エッジケースを考慮し、アプリケーションの安定性を高める

正直、1. APIレスポンスの修正によってエラーは解消した。
しかし、これらの原則を守ることで、より安定したアプリケーションを維持できる。
Next.jsとPrismaを使用したアプリケーション開発において、これらの点に注意を払うことで、多くの潜在的な問題を事前に防ぐことができる。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?