6: Todoの追加
このステップで学ぶこと
Section titled “このステップで学ぶこと”前回はTodoの表示機能を作りました。
今回は新しいTodoを追加する機能を作っていきましょう。
- フォームの基本的な使い方
- 状態管理の方法
- イベントハンドリング
このステップでは、フォームを使った入力処理の基本を学びます。
Todo追加機能の作成
Section titled “Todo追加機能の作成”src/app/todos/page.js
を以下の内容に更新します。
'use client';import { useState } from 'react';import style from './page.module.css';
export default function Todos() { // 1. Todoデータをステートとして管理する const [todos, setTodos] = useState([ { id: 1, title: '買い物に行く', completed: false }, { id: 2, title: 'メールを確認する', completed: false }, { id: 3, title: '資料を作成する', completed: false }, { id: 4, title: '友達に電話する', completed: false }, { id: 5, title: '部屋の掃除', completed: false }, ]);
// 2. 入力値をステートとして管理する const [newTodo, setNewTodo] = useState('');
// 3. Todoをリストに追加する const handleSubmit = (e) => { e.preventDefault(); if (newTodo.trim() === '') return;
const newId = todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1; setTodos([...todos, { id: newId, title: newTodo, completed: false }]); setNewTodo(''); };
return ( <section className={style.container}> <h1>Todoリスト</h1>
{/* 4. Todo入力フォーム */} <form className={style.form} onSubmit={handleSubmit}> <input type="text" value={newTodo} onChange={(e) => setNewTodo(e.target.value)} placeholder="新しいTodoを入力" className={style.input} /> <button type="submit" className={style.button}>追加</button> </form>
{/* Todo一覧 */} <div className={style.checkbox}> {todos.map((todo) => ( <div key={todo.id}> <label> <input type="checkbox" checked={todo.completed} onChange={(e) => {console.log(e.target.checked)}} /> {todo.title} </label> </div> ))} </div> </section> );}
コードの解説
Section titled “コードの解説”-
Todoデータをステートとして管理する
- コンポーネントの状態としてTodo一覧を保持するようにします
-
入力値をステートとして管理する
- テキストボックスに入力された値をコンポーネントの状態として保持するようにします
-
Todoをリストに追加する
const handleSubmit = (e) => {e.preventDefault();if (newTodo.trim() === '') return;const newId = todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1;setTodos([...todos, { id: newId, title: newTodo, completed: false }]);setNewTodo('');};e.preventDefault()
: 追加ボタンが押されたときにページがリロードされるデフォルトの挙動を抑制しますnewTodo.trim()
: 入力された文字の前後の空白を削除しますif (newTodo.trim() === '') return
: 空のTodoは追加しないようにしますtodos.length > 0 ? ... : 1
: Todoが1つもない場合に新しい ID を1にしますsetTodos([...todos, { id: newId, title: newTodo, completed: false }])
: 新しいTodoを配列に追加しますsetNewTodo('')
: Todo入力フォームを空にします
-
Todo入力フォーム
<form className={style.form} onSubmit={handleSubmit}><inputtype="text"value={newTodo}onChange={(e) => setNewTodo(e.target.value)}placeholder="新しいTodoを入力"className={style.input}/><button type="submit" className={style.button}>追加</button></form>onSubmit
: 追加ボタンが押されたときの処理を指定します
ここではTodoをリストに追加する処理を指定していますvalue
: テキストボックスに表示する値を指定しますonChange
: テキストボックス内容が変わったときの処理を指定します
ここでは新しい値を保存していますplaceholder
: 入力フォームが空のときに表示する説明を指定します
Todo入力フォームのスタイリング
Section titled “Todo入力フォームのスタイリング”src/app/todos/page.module.css
に以下のスタイルを追加します。
/* 省略 */
.checkbox input { display: none;}
.form { display: flex; gap: 1rem; margin-bottom: 2rem;}
.input { flex: 1; padding: 0.5rem; border: 1px solid #ccc; border-radius: 3px;}
.button { padding: 0.5rem 1rem; background-color: #0070f3; color: white; border: none; border-radius: 3px; cursor: pointer;}
.button:hover { background-color: #0051a2;}
🚀 動作確認
Section titled “🚀 動作確認”正しく動作しているか確認しましょう。
- 追加ボタンをクリックするとTodoが追加される
- 追加後に入力フィールドがクリアされる
- 空のTodoは追加できない
よくある問題と解決方法
Section titled “よくある問題と解決方法”追加ボタンを押しても追加されない
preventDefault()
が正しく呼び出されているか確認- フォームの
onSubmit
イベントが正しく設定されているか確認 - 状態更新関数が正しく呼び出されているか確認
🎯 理解度チェック
Section titled “🎯 理解度チェック”以下の質問に答えて、学習内容を確認しましょう!
-
Reactで状態を管理するために使用するフックは?
- A:
useEffect
- B:
useState
- C:
useContext
- D:
useReducer
- A:
-
フォームの送信を防止するために使用するメソッドは?
- A:
stopPropagation()
- B:
preventDefault()
- C:
stopImmediatePropagation()
- D:
cancelBubble()
- A:
答えを見る
答え: B: preventDefault()
preventDefault()
はイベントのデフォルトの動作を防止します- 今回は追加ボタンを押した時にページがリロードされるのを防ぐために使いました
このステップでは以下について学びました。
-
フォームの基本
- 入力フィールドの作成
- フォーム送信の処理
- 入力値のバリデーション
-
状態管理
useState
フックの使用- 状態の更新方法
- 配列の操作
-
イベントハンドリング
- フォーム送信イベント
- 入力値の変更イベント
- イベントのデフォルト動作の防止