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

【React 100本ノック #002】Todoアプリを作ってuseState・map・filterを理解する

0
Posted at

はじめに

React 100本ノックの2作品目です。
今回は、React + TypeScriptでシンプルなTodoアプリを作りました。
#001では学習記録アプリを作り、useStatemap()などReactの基本的な使い方を学びました。

今回はそこから一歩進んで、

  • Todoの追加
  • Todoの一覧表示
  • Todoの完了・未完了
  • Todoの削除
  • Todo件数の表示

を実装します。

特に、Reactで配列のデータを追加・更新・削除する方法を理解することを目的としました。


今回の目的

今回の目的は、単にTodoアプリを完成させることではありません。

以下のReactの基本を、実際にコードを書きながら理解することを目的としました。

useState
↓
データを管理する

map()
↓
データを一覧表示・更新する

filter()
↓
データを絞り込んで削除する

使用技術

  • React
  • TypeScript
  • Vite

作ったもの

主な機能

  • Todoを追加
  • Todoを一覧表示
  • Todoを完了にする
  • Todoを未完了に戻す
  • Todoを削除
  • Todoの総数を表示
  • 未完了のTodo数を表示

画面

スクリーンショット 2026-08-12 22.36.39.png


ローカル環境構築

1. プロジェクト作成

npm create vite@latest react-002-todo-app -- --template react-ts

React + TypeScriptのプロジェクトをViteで作成します。

2. プロジェクトへ移動

cd react-002-todo-app

3. パッケージをインストール

npm install

4. 開発サーバーを起動

npm run dev

ブラウザから以下にアクセスします。

http://localhost:5173/

Todoのデータ構造

まず、Todoがどのようなデータなのかを定義しました。

type Todo = {
  id: number;
  title: string;
  completed: boolean;
};

例えば、以下のようなデータになります。

{
  id: 1,
  title: "Reactを勉強する",
  completed: false
}

それぞれの役割は以下の通りです。

プロパティ 意味
id Todoを識別するためのID
title Todoの内容
completed Todoが完了しているか

useStateでTodoを管理する

Todo一覧をuseStateで管理しました。

const [todos, setTodos] = useState<Todo[]>([]);

最初はTodoがないため、

[]

という空の配列です。

Todoが追加されると、

[]
 ↓
[Reactを勉強する]
 ↓
[Reactを勉強する, TypeScriptを勉強する]

のようにstateが変化していきます。

Reactではstateが変更されると、それに合わせて画面も更新されます。


Todoを追加する

Todoの追加処理は以下のようにしました。

const handleAddTodo = () => {
  if (!title.trim()) {
    return;
  }

  const newTodo: Todo = {
    id: Date.now(),
    title: title,
    completed: false,
  };

  setTodos([...todos, newTodo]);

  setTitle("");
};

ここで重要なのが、

setTodos([...todos, newTodo]);

です。

例えば現在、

[A, B]

というTodoがあるとします。

そこにCを追加すると、

[A, B, C]

になります。

...todosによって現在のTodoを展開し、その後ろにnewTodoを追加しています。


Todoを一覧表示する

Todoの表示にはmap()を使いました。

{todos.map((todo) => (
  <li key={todo.id}>
    {todo.title}
  </li>
))}

map()は配列のデータを1つずつ取り出して処理できます。

例えば、

[A, B, C]

という配列があれば、

A
B
C

と1つずつ処理できます。

Todoアプリでは、

todos
 ↓
map()
 ↓
Todoを1件ずつ取り出す
 ↓
画面に表示

という流れです。


Todoを完了・未完了にする

次にTodoの状態を変更します。

const handleToggleTodo = (id: number) => {
  setTodos(
    todos.map((todo) =>
      todo.id === id
        ? { ...todo, completed: !todo.completed }
        : todo
    )
  );
};

少し難しい処理ですが、やっていることはシンプルです。

Todoを1件ずつ確認
        ↓
変更したいTodo?
    ↙       ↘
   YES       NO
    ↓         ↓
状態を変更   そのまま

例えば、

completed: false

だった場合、

!todo.completed

によって、

false → true

になります。

もう一度押せば、

true → false

となります。


Todoを削除する

削除にはfilter()を使いました。

const handleDeleteTodo = (id: number) => {
  setTodos(todos.filter((todo) => todo.id !== id));
};

例えば、

[A, B, C]

からBを削除したい場合、

A → 残す
B → 削除
C → 残す

となり、

[A, C]

という新しい配列になります。

今回のポイントは、

todo.id !== id

です。

つまり、

「削除したいIDではないTodoだけ残す」

という処理になっています。


Todoの件数を表示する

Todoの総数は、

todos.length

で取得できます。

<p>全て:{todos.length}</p>

さらに、未完了のTodoだけを取得するためにfilter()を使いました。

const incompleteCount = todos.filter(
  (todo) => !todo.completed
).length;

これによって、

Todo 3件
↓
完了 1件
↓
未完了 2件

というように未完了の件数を表示できます。


🏐 バレーボールに例えて理解する

今回のReactの処理をバレーボールに例えてみました。

Todoを追加

新しい選手がチームに入るイメージです。

選手A
選手B

↓

選手A
選手B
選手C
setTodos([...todos, newTodo]);

Todoを更新

選手の状態を変更するイメージです。

ベンチ
 ↓
試合に出る
map()

Todoを削除

チームから選手を外すイメージです。

選手A
選手B ← 外す
選手C

↓

選手A
選手C
filter()

このように考えると、

追加 → [...todos]
表示 → map()
更新 → map()
削除 → filter()

という役割の違いをイメージしやすくなりました。


CRUDについて

今回のTodoアプリでは、CRUDの基本も体験しました。

操作 CRUD Todoアプリ
作成 Create Todoを追加
取得 Read Todoを表示
更新 Update 完了・未完了を変更
削除 Delete Todoを削除

まだデータベースやAPIは使っていませんが、

「データを作る・見る・変更する・削除する」

という基本的な考え方をReact上で体験できました。


#001から何が変わったか

#001では、

入力
 ↓
state
 ↓
表示

というReactの基本的な流れを学びました。

#002では、

入力
 ↓
state
 ↓
追加
 ↓
表示
 ↓
更新
 ↓
削除

まで扱いました。

特に今回、

map()

filter()

を実際に使ってみたことで、Reactで配列を操作するイメージが少し掴めました。


今回の学び

今回のTodoアプリを作ってみて、特に理解したかったのは、

Reactではstateを変更すると、その変更に合わせて画面が更新される

という考え方です。

例えば、

Todoを追加
 ↓
setTodos()
 ↓
todosが変わる
 ↓
Reactが再描画
 ↓
Todo一覧が変わる

という流れになります。

単純なTodoアプリですが、Reactの基本的な考え方を理解するには良い題材だと感じました。



次回

次回は、React 100本ノック #003に進みます。

#003では、今回学んだfilter()をさらに発展させて、

商品一覧
 ↓
検索
 ↓
カテゴリ絞り込み
 ↓
検索結果表示

という商品検索アプリを作る予定です。


📚 React 100本ノック

作成物 学習内容
#001 学習記録アプリ useState / map / reduce
#002 Todo App useState / map / filter / CRUD
#003 商品検索アプリ 検索 / 絞り込み
#004〜 Coming Soon Coming Soon

🔗 GitHub

GitHubリポジトリ:

https://github.com/spring46-stack/react-002-todo-app


まとめ

今回はTodoアプリを作りながら、

useState
map()
filter()
CRUD

について学びました。

特に、

追加 → [...todos]
表示 → map()
更新 → map()
削除 → filter()

という使い分けを実際にコードを書きながら理解できたのが今回の一番の収穫でした。

React 100本ノック、2/100完了です。

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