Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9145

Next.jsで簡単なTodoページを作成してみた

$
0
0
初めに 今回、久しぶりにプログラミングの勉強をしようということで流行りのReactを勉強しました。 どうせならNext.jsも使って簡単なものを作ろうと思い、今回はTodoアプリを作成しました。 環境 Docker Next.js TypeScript TailwindCSS Dockerでの環境構築 ネットでたくさん出回っていますが、私は下記サイトを参考にしました。 https://zenn.dev/tasuya/articles/da033574b85e6d ヘッダーを追加する ほとんどのサイトではどのページに行っても、ヘッダーがあると思うので、ヘッダーを作成します $ mkdir components $ touch ./components/Header.tsx Header.tsxの中身は下記です(タイトルをクリックするとトップページに戻れるようにリンクを設定しています) Header.tsx import Link from 'next/link' export default function Header() { return ( <header className="text-gray-600 body-font bg-blue-500"> <div className="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"> <Link href={'/'} passHref> <a className="flex title-font font-medium items-center text-gray-900 mb-4 md:mb-0"> <span className="ml-3 text-xl text-white">My Blog</span> </a> </Link> <nav className="md:ml-auto flex flex-wrap items-center text-base justify-center"> <a className="mr-5 text-white hover:text-gray-900">Profile</a> </nav> </div> </header> ) } 最後にヘッダー部分を全体のページに適用させるように_app.tsxを下記に修正 _app.tsx import '../styles/globals.css'; import type { AppProps } from 'next/app'; + import Header from '../components/Header'; function MyApp({ Component, pageProps }: AppProps) { - return <Component {...pageProps} />; + return ( + <> + <Header /> + <Component {...pageProps} /> + </> + ); } export default MyApp; 画像のようになっていれば成功です。 Todoの作成 では、本題のTodoページを作成していきたいと思います。 最初にコンポーネント(部品)作っていこうと思います。 シンプルに2つの部品を作っていきます。 Todoのリスト Todoを追加するためのフォーム では、componentsディレクトリ直下にファイルを作成します。 $ touch ./components/{todoForm.tsx,todoList.tsx} Todoのリストの方を下記にする ※画像は「./public/ハリネズミ.jpg」に配置する(画像名は自分で決めても問題ないです) todoList.tsx import type { Todo } from "../types/todolist" type Props = { todolist: Todo } export default function TodoList( { todolist }: Props) { return ( <> <div className="p-2 lg:w-1/3 md:w-1/2 w-full"> <div className="h-full flex items-center border-gray-200 border p-4 rounded-lg"> <img className="w-16 h-16 bg-gray-100 object-cover object-center flex-shrink-0 rounded-full mr-4" src="/ハリネズミ.jpeg" alt="icon" /> <div className="flex-grow"> <h2 className="text-gray-900 title-font font-medium">{ todolist.title}</h2> <p className="text-gray-500">{todolist.body}</p> </div> </div> </div> </> ) } Todoを追加するためのフォームを下記にする todoForm.tsx export default function TodoForm( {handleadd} ) { return ( <> <form className="font-sans text-sm rounded w-full max-w-md mx-auto my-8 px-8 pt-6 pb-8" onSubmit={handleadd}> <div className="relative border rounded mb-4 shadow appearance-none label-floating"> <input className="w-full py-2 px-3 text-gray-700 leading-normal rounded" id="todotitle" type="text" placeholder="todotitle" name="todotitle" /> <label className="absolute block text-gray-700 top-0 left-0 w-full px-3 py-2 leading-normal"> </label> </div> <div className="flex items-center justify-between"> <input type="submit" value="投稿" /> </div> </form> </> ) } 次にTodoの構成を型宣言していく 新たにtypesディレクトリを作成し、todolist.tsを作成する $ mkdir ./types $ touch ./types/todolist.ts todolist.tsの値を下記にする todolist.ts export type Todo = { id: number createdAt: string title: string body: string tag: string } pegesディレクトリ直下にtodoディレクトリを作成し、その直下にindex.tsxを作成します。 $ mkdir ./pages/todo $ touch ./pages/todo/index.tsx index.tsxを下記にする index.tsx import TodoList from "../../components/todoList" import type { Todo } from "../../types/todolist" import TodoForm from "../../components/todoForm" import React, { useState } from "react" type Props = { todolists: Array<Todo> } export default function Index({ todolists }: Props) { const [todos, settodo] = useState(todolists) const handle_add = async (event:any)=>{ event.preventDefault() const data = { id: todos.length + 1, createdAt: "2022-02-02", title: event.target.todotitle.value, body: "テストテスト", tag: "特になし" } settodo([ ...todos, data]) console.log(todolists) event.target.todotitle.value='' } return ( <> <section className="text-gray-600 body-font"> <div className="container px-5 py-24 mx-auto"> <TodoForm handleadd = {handle_add} /> <div className="flex flex-col text-center w-full mb-20"> <h1 className="sm:text-3xl text-2xl font-medium title-font mb-4 text-gray-900">Todo</h1> </div> <div className="flex flex-wrap -m-2"> { todos.map(todolist =>( <TodoList todolist={todolist}></TodoList> ))} </div> </div> </section> </> ) } export const getStaticProps = async () => { const url = process.env.JSON_FILE const req = await fetch( url ) const json = await req.json() return { props: { todolists: json } } } 最後にTodoの内容を記載したjsonファイルを配置し、envファイルを修正する 下記ディレクトリにファイルを配置 $ touch ./public/todo.json jsonファイルを下記にする todo.json [ { "id": 1, "created_at": "2022-02-11T15:59:15.693Z", "title": "todo1", "body": "テストです1", "tag": "特になし" }, { "id": 2, "created_at": "2022-02-11T15:59:15.693Z", "title": "todo1", "body": "テストです2", "tag": "特になし" }, { "id": 3, "created_at": "2022-02-11T15:59:15.693Z", "title": "todo1", "body": "テストです3", "tag": "特になし" } ] envファイルを作成し、内容を記載する(envファイルとは環境変数を入れるファイルのこと) ※3000のところは設定したポート番号を記載してください。 $ touch ./public/.env.local env.local JSON_FILE=http://localhost:3000/todo.json Todoページにアクセス 画像のようになっていれば成功です テキストボックスに「テスト」と入力して「投稿」をクリックするとtodoが追加される まとめ 今回ですが、簡単なTodoサイトを作成しました。 jsonのところをデータベースから取得するようにすれば書き換え可能なTodoサイトを作成できます。 TypeScriptで書いてるのですが、所々型宣言が抜けているところがあるため、学習を今後も続けていきたいです。 普段はPHP,Rubyを書いてることが多いですが、TypeScriptも楽しいですね〜

Viewing all articles
Browse latest Browse all 9145

Trending Articles