実践:ReactでTODOアプリを作る(追加・表示・削除)- 11/12

これまでの知識(コンポーネント、props、state、イベント、リスト表示)をまとめて使います。まずは最小のTODOを作り、次回以降の拡張にも耐える設計にします。

完成イメージと仕様

最小仕様は次の通りです。

  • 入力欄にTODOを入れる
  • 追加ボタンでリストに追加
  • 各行に削除ボタンを付ける

追加要件(任意):

  • 空文字は追加しない
  • Enterで追加
  • 件数表示

まずは1ファイルで作る(App.jsx)

App.jsx を以下に置き換えて動かしてみます。

import { useState } from "react"

export default function App() {
  const [todos, setTodos] = useState([])
  const [text, setText] = useState("")

  const addTodo = () => {
    const trimmed = text.trim()
    if (!trimmed) return

    const newTodo = {
      id: Date.now(),
      text: trimmed,
    }

    setTodos([...todos, newTodo])
    setText("")
  }

  const removeTodo = (id) => {
    setTodos(todos.filter((t) => t.id !== id))
  }

  return (
    <div style={{ padding: 16 }}>
      <h1>TODO</h1>

      <div style={{ display: "flex", gap: 8 }}>
        <input
          value={text}
          onChange={(e) => setText(e.target.value)}
          placeholder="やることを入力"
        />
        <button onClick={addTodo}>追加</button>
      </div>

      <p>件数: {todos.length}</p>

      <ul>
        {todos.map((t) => (
          <li key={t.id} style={{ display: "flex", gap: 8 }}>
            <span>{t.text}</span>
            <button onClick={() => removeTodo(t.id)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

ポイント:

  • 追加:setTodos([...todos, newTodo])
  • 削除:filter で除外
  • 入力:valueonChange でstateと同期

よくある改善:Enterで追加

入力欄に onKeyDown を入れてEnterで追加できます。

onKeyDown={(e) => {
  if (e.key === "Enter") addTodo()
}}

このようにイベントを足すだけで操作性が上がります。

次の改善:コンポーネント分割

TODOが動いたら、次の分割をするとReactらしい設計になります。

  • TodoInput:入力と追加ボタン
  • TodoList:一覧表示
  • TodoItem:1行

次回は「次に学ぶ」回で、API通信やRouterへ進む道筋を示します。

練習問題

  1. TODOが0件のとき「まだTODOがありません」と表示してみましょう。
  2. 完了チェック(true/false)を付けて、完了は打ち消し線にしてみましょう。
  3. localStorageに保存して、リロードしても残るようにしてみましょう(ヒント:useEffect)。

コメント

タイトルとURLをコピーしました