1
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?

More than 1 year has passed since last update.

【03】Next.js14でTodoアプリ作成(INSERT編)

Last updated at Posted at 2024-01-18

はじめに

Next.jsの知識を深めるために、Todoアプリを作ることにしました。そのメモを残しておきます。今回はデータ挿入についてのメモを残します。何か間違っていることなどございましたらコメントいただけますと、とても喜びます。

今までの記事

環境構築編

https://qiita.com/naoyuki2/items/e974c630c6cbd3c55254

【01】Next.js14でTodoアプリ作成(CREATE編)

https://qiita.com/naoyuki2/items/7474d448de7769905d82

【02】Next.js14でTodoアプリ作成(SELECT編)

https://qiita.com/naoyuki2/items/2d8ad09f767f818e8860

今回のゴール

データ挿入ができる

image.png

1.APIの作成(POSTメソッド)

POSTメソッドの記述

src/app/api/todo/route.tsPOSTメソッドを記述していく。GETメソッドがすでにあるのでその下に書く。

src/app/api/todo/route.ts
export async function POST(request: Request) {
    // todoテーブルに新規レコードを追加
    const body = await request.json()
    try {
        const todo: todo = await prisma.todo.create({
            data: {
                title: body.title,
            },
        })
        return NextResponse.json(todo)
    } catch (error) {
        return NextResponse.json(error)
    }
}

コード解説

export async function POST(request: Request) {

この関数はHTTPリクエストを引数として受け取る。

Requestという型がNext.jsで用意されているらしく、importせずとも使えるらしい。反対にResponseという型もある。

const body = await request.json():

この行は、受け取ったレスポンスからJSONデータを非同期に解析する。この中にtitleが入っている。

const todo: todo = await prisma.todo.create({
    data: {
        title: body.title,
    },
})

Prismacreate関数を使用して新しいtodoレコードをデータベースに挿入する。SQLでいうINSERT INTO "todo" (title) values (body.title)みたいなこと。

return NextResponse.json(todo)

新しく作成された"todo"レコードをJSON形式で返す。

2.フロントエンドの実装

全部載せてるんで見ずらい。ごめんなさい。+がついている緑の行を前回から新たに追加した。

コードの全体

src/app/page.tsx
'use client'

import { useEffect, useState } from 'react'
import { todo } from '@prisma/client'

export default function Home() {
    const [todos, setTodos] = useState<todo[]>([])
+   const [inputVal, setInputVal] = useState<string>('')

    useEffect(() => {
        const getTodo = async () => {
            const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/todo`)
            const data = await res.json()
            setTodos(data)
        }
        getTodo()
    }, [])

+   const postTodo = async () => {
+       if (!inputVal) return alert('タイトルを入力してください')
+       const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/todo`, {
+           method: 'POST',
+           headers: {
+               'Content-Type': 'application/json',
+           },
+           body: JSON.stringify({
+               title: inputVal,
+           }),
+       })
+       const data = await res.json()
+       setTodos([...todos, data])
+       setInputVal('')
+   }

    return (
        <>
+           <input
+               placeholder="タイトル入力"
+               value={inputVal}
+               onChange={(e) => setInputVal(e.target.value)}
+           />
+           <button onClick={() => postTodo()}>追加</button>
            {todos.map((todo) => (
                <div key={todo.id}>
                    <p>{todo.id}</p>
                    <p>{todo.title}</p>
                    <p>{todo.content}</p>
                    <p>{todo.isDone}</p>
                    <p>{new Date(todo.createdAt).toLocaleString()}</p>
                    <p>{new Date(todo.updatedAt).toLocaleString()}</p>
                </div>
            ))}
        </>
    )
}

コードの解説

const [inputVal, setInputVal] = useState<string>('')

タイトルを入力するinput要素のvalue属性を管理するためにuseStateを使用する。

postTodo
const postTodo = async () => {
    if (!inputVal) return alert('タイトルを入力してください')...

postTodo関数を実行時にinputValの中身が空だった場合はアラートを出し、returnがあるのでここで関数が終了する。

postTodo
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/todo`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        title: inputVal,
    }),
})

前々回の記事.envファイルにAPIルートを書いているため、今回も流用する。

今回はPOSTメソッドなのでmethodタイプを記述する。

JSON形式でやり取りするため、headersにこのような記述をする。

bodyにはAPIに渡すものを記述する。今回はtitleのみでいいのでtitle情報を保持しているinputValを渡す。

const data = await res.json()
setTodos([...todos, data])
setInputVal('')

返ってきたレスポンスをJSON形式でdataに代入する。

useStatesetTodostodosにデータを入れる。

...todosはスプレッド構文といって配列の中身を展開することができる。todosを展開して、dataを新しく追加している。

setInputVal('')input要素を空にして次のタイトルを入力しやすいようにしている。

<input
    placeholder="タイトル入力"
    value={inputVal}
    onChange={(e) => setInputVal(e.target.value)}
/>

valueにはuseStateinputValを設定する。

そして、onChangeイベントを設定することでinput要素の中身が変更されるたびにinputValの値を更新している。

<button onClick={() => postTodo()}>追加</button>

onClickイベントにより、先ほど作ったpostTodo関数を呼び出している。

3.挿入できるか試す!

これでおそらくデータの挿入ができるはず!!

空だったら下のようにアラートが出る。

image.png

テストと入力して、追加をクリックすると下にテストというデータが追加されるはず。

image.png

おわりに

POSTはまだ簡単な気がする。UPDATEDELETEは条件が増えて大変そう。

1
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
1
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?