Skip to content

6: Todoの追加

前回はTodoの表示機能を作りました。
今回は新しいTodoを追加する機能を作っていきましょう。

  1. フォームの基本的な使い方
  2. 状態管理の方法
  3. イベントハンドリング

このステップでは、フォームを使った入力処理の基本を学びます。

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>
);
}
  1. Todoデータをステートとして管理する

    • コンポーネントの状態としてTodo一覧を保持するようにします
  2. 入力値をステートとして管理する

    • テキストボックスに入力された値をコンポーネントの状態として保持するようにします
  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('');
    };
    • 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入力フォームを空にします
  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>
    • 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;
}

正しく動作しているか確認しましょう。

  • 追加ボタンをクリックするとTodoが追加される
  • 追加後に入力フィールドがクリアされる
  • 空のTodoは追加できない

追加ボタンを押しても追加されない

  • preventDefault() が正しく呼び出されているか確認
  • フォームの onSubmit イベントが正しく設定されているか確認
  • 状態更新関数が正しく呼び出されているか確認

以下の質問に答えて、学習内容を確認しましょう!

  1. Reactで状態を管理するために使用するフックは?

    • A: useEffect
    • B: useState
    • C: useContext
    • D: useReducer
答えを見る

答え: B: useState

  • useState はコンポーネント内で状態を管理するための基本的なフックです
  • 状態の値と、それを更新する関数のペアを返します
  • 参考: useState
  1. フォームの送信を防止するために使用するメソッドは?

    • A: stopPropagation()
    • B: preventDefault()
    • C: stopImmediatePropagation()
    • D: cancelBubble()
答えを見る

答え: B: preventDefault()

  • preventDefault() はイベントのデフォルトの動作を防止します
  • 今回は追加ボタンを押した時にページがリロードされるのを防ぐために使いました

このステップでは以下について学びました。

  • フォームの基本

    • 入力フィールドの作成
    • フォーム送信の処理
    • 入力値のバリデーション
  • 状態管理

    • useState フックの使用
    • 状態の更新方法
    • 配列の操作
  • イベントハンドリング

    • フォーム送信イベント
    • 入力値の変更イベント
    • イベントのデフォルト動作の防止