【初心者向け】Reactを使ったTodoアプリの作り方を解説
Reactを勉強するためにYouTubeでTodoアプリの作成したけど、全く理解できない。
今回はReactの知識ゼロの筆者がわかりやすくTodoアプリのコードを解説していきます。
↓↓↓参考にして作ったYouTube↓↓↓
Contents
Todoアプリの動作を簡単にまとめ
1.ToDoアイテムの管理:
ユーザーが入力したToDoアイテムはリストで管理。
2.ToDoアイテムの追加:
ユーザーが新しいToDoアイテムを入力すると、それがリストに追加。
3.ToDoアイテムの完了マーク:
ユーザーがToDoアイテムをクリックすると、そのアイテムが完了したことにマークされる。
4.完了したToDoアイテムの削除:
ユーザーが削除ボタンをクリックすると、完了したToDoアイテムがリストから削除。
これらの操作は、状態変数todos
と更新関数setTodos
を使用してReactコンポーネント内で処理されます。そして、これによってToDoリストはユーザーの入力や操作に応じて動的に変化し、リアルタイムで表示が更新されます。
ファイル構造を視覚化
コードを視覚的に理解しやすくするために、コンポーネント間の関係を示す簡単な設計図です。以下のような構造を持つReactアプリケーションになります。
一つずつそれぞれのファイルについて説明していきます。
App
├─ TodoList
│ └─ Todo (複数)
└─ フォームとボタン
App.js
App: アプリケーション全体を表して、その中に「TodoList=ToDoリスト」「Todo=ToDoの追加フォーム」「フォームとボタン=完了したToDoの削除ボタン」が含まれます。
TodoList.js
TodoListは、ToDoアイテム*¹のリストを表示するためのコンポーネント*³です。つまり、ToDoリスト*²全体を表示するための部品になります。
TodoListは、ToDoアイテムを複数持つことができます。つまり、Todoコンポーネント(Todo.jsの中身)を複数保持します。
TodoListの役割は、ToDoアイテムのリストを画面に表示することです。そのため、TodoListはToDoアイテムを画面上に一覧表示します。そして、それぞれのToDoアイテムを表示するために、Todoコンポーネントを使います。
Todo.js
Todo.jsは、ToDoリスト内の1つのToDoアイテムを表示するためのコンポーネントです。
ToDoリスト内の個々のToDoアイテムを表示し、ユーザーがそれらのアイテムの完了状態を切り替えることができるようにします。
フォームとボタン
フォームとボタンは、ユーザーがToDoリストに新しいタスクを追加したり、タスクを削除したりするための機能です。
フォーム: フォームは、ユーザーがテキスト入力フィールドにタスクを入力し、その内容を送信するためのUI要素です。ToDoリストに新しいタスクを追加する際に使用されます。ユーザーがテキスト入力フィールドにタスクを入力し、フォームを送信すると、新しいタスクがToDoリストに追加されます。
ボタン: ボタンは、ユーザーが特定のアクションを実行するためのUI要素です。ToDoリストでは、一般的に「タスクを追加」や「完了したタスクの削除」といったアクションを実行するためのボタンが表示されます。
*¹ToDoアイテムとは、ユーザーが入力したタスクや予定
*²ToDoリストとは、ToDoアイテムの集合体
*³コンポーネントとは、Reactアプリケーション内で再利用可能な部品
ReactのTodoアプリコードを理解-App.js-
import { useState, useRef } from "react";
import TodoList from "./TodoList";
import { v4 as uuidv4 } from "uuid";
function App() {
const [todos, setTodos] = useState([]);
//ToDoアイテムの管理
const todoNameRef = useRef();
const handleAddTodo = () => {
const name = todoNameRef.current.value;
if (name === "") return;
setTodos((prevTodos) => {
return [...prevTodos, { id: uuidv4(), name: name, completed: false }];
});
todoNameRef.current.value = null;
};
//ToDoアイテムの追加
const toggleTodo = (id) => {
const newTodos = [...todos];
const todo = newTodos.find((todo) => todo.id === id);
todo.completed = !todo.completed;
setTodos(newTodos);
};
//ToDoアイテムの完了状態の切り替え
const handleClear = () => {
const newTodos = todos.filter((todo) => !todo.completed);
setTodos(newTodos);
};
//完了したタスクの削除
return (
<>
<TodoList todos={todos} toggleTodo={toggleTodo} />
<input type="text" ref={todoNameRef} />
<button onClick={handleAddTodo}>タスクを追加</button>
<button onClick={handleClear}>完了したタスクの削除</button>
<div>残りのタスク:{todos.filter((todo) => !todo.completed).length}</div>
</>
);
//UIの表示
}
export default App;
1. ToDoアイテムの管理: `useState` フックを使用して、ToDoアイテムの状態を管理します。`todos` はToDoアイテムの配列であり、`setTodos` 関数を使用してその状態を更新します。
2. ToDoアイテムの追加: `handleAddTodo` 関数は、ユーザーが入力したタスクをToDoリストに追加します。`useState` フックで管理されている `todos` 配列に新しいToDoアイテムを追加し、`uuidv4` ライブラリを使用してそのToDoアイテムに一意のIDを割り当てます。
3. ToDoアイテムの完了状態の切り替え: `toggleTodo` 関数は、ユーザーがToDoアイテムのチェックボックスをクリックしたときに、そのToDoアイテムの完了状態を切り替えます。特定のIDを持つToDoアイテムを見つけて、その完了状態を反転させます。
4. 完了したタスクの削除: `handleClear` 関数は、完了したタスクをToDoリストから削除します。`filter` メソッドを使用して、完了していないタスクだけを残して新しいToDoアイテムの配列を作成し、それを `setTodos` 関数を使って更新します。
5. UIの表示: JSXを使用して、ToDoリストのUIを表示します。`TodoList` コンポーネントを使用して、ToDoアイテムのリストを表示し、ToDoアイテムを追加するための入力フィールドとボタン、完了したタスクを削除するためのボタン、残りのタスクの数を表示します。
これにより、ToDoリストのUIと機能が実装されます。ユーザーは新しいタスクを追加し、タスクの完了状態を切り替え、完了したタスクを削除することができます。
ToDoアイテムの管理
const [todos, setTodos] = useState([]);
const todoNameRef = useRef();
1.const [todos, setTodos] = useState([]);
useState([])
は React のuseState
フックを呼び出し、todos
という名前の状態変数と、その状態を更新するための関数setTodos
を生成します。
todos
は現在のToDoアイテムの配列を保持します。初期値は空の配列[]
です。
2.const todoNameRef = useRef();
useRef()
は React のuseRef
フックを呼び出し、todoNameRef
という名前の参照オブジェクトを生成します。
- この参照は、後でToDoアイテムを追加するための入力フィールドへの参照を保持します。
これらの部分は、Reactのフックを使用してToDoアイテムの管理と、入力フィールドへの参照の作成を行っています。todos
はToDoアイテムの状態を保持し、todoNameRef
は新しいToDoアイテムの名前を入力するための参照を提供します。
ReactフックuseState
Reactコンポーネント内で状態を管理するために使用。コンポーネント内で変更される可能性のあるデータを表す。1.useState フックをインポート
↓ pic.twitter.com/9bWlt2AV3Y— もりだい@エンジニア挑戦中 (@moridai1104) April 30, 2024
3.具体的使用例
この例では、useState を使用して count という状態変数を作成し、setCount を使用してその値を更新。 pic.twitter.com/s4BkbhuSv2— もりだい@エンジニア挑戦中 (@moridai1104) April 30, 2024
ReactのフックuseRef
useRef フックは、Reactコンポーネント内でDOM要素への参照を作成するために使用。DOM要素への直接的なアクセスや操作が可能に
1.useRef フックをインポート
↓ pic.twitter.com/oAQTkN7BsQ— もりだい@エンジニア挑戦中 (@moridai1104) April 30, 2024
3.具体的使用例
この例では、useRef を使用して inputRef という参照を作成し、inputRef.current を使用して input 要素に直接アクセス。 pic.twitter.com/NvWEr5pyek— もりだい@エンジニア挑戦中 (@moridai1104) April 30, 2024
ToDoアイテムの追加
React作ったToDリスト
ToDoアイテムの追加 pic.twitter.com/3FQ9qDkbhw— もりだい@エンジニア挑戦中 (@moridai1104) May 2, 2024
const handleAddTodo = () => {
const name = todoNameRef.current.value;
if (name === "") return;
setTodos((prevTodos) => {
return [...prevTodos, { id: uuidv4(), name: name, completed: false }];
});
todoNameRef.current.value = null;
};
この `handleAddTodo` 関数は、新しいToDoアイテムを追加するための機能です。
1. const name = todoNameRef.current.value;
todoNameRef.current
を使用して、入力フィールドの現在の値(ユーザーが入力したタスクの名前)を取得します。
2. if (name === "") return;
- 取得した名前が空であるかどうかをチェックします。もし空であれば、何もせずに関数を終了します。
3. setTodos((prevTodos) => { return [...prevTodos, { id: uuidv4(), name: name, completed: false }]; });
setTodos
関数を使用して、現在のToDoリストに新しいToDoアイテムを追加します。prevTodos
は前回のToDoリストを表し、新しいToDoアイテムを追加するためにそれを展開して新しい配列を作成します。- スプレッド演算子を使用して、元のToDoアイテムの配列を展開し、新しいToDoアイテムを追加します。
- 新しいToDoアイテムは、一意のID(`uuidv4()` を使用して生成)、入力された名前、および `completed` フラグ(初期値は `false`)を持つオブジェクトです。
4. todoNameRef.current.value = null;
- ToDoアイテムが追加された後、入力フィールドをクリアして次のToDoアイテムの入力を容易にします。
このようにして、`handleAddTodo` 関数は、入力された名前を取得し、空でないことを確認した後にToDoアイテムを追加し、入力フィールドをクリアするという機能を持ちます。
スプレッド演算子
配列やオブジェクトを展開して、その要素やプロパティを取り出すときに使われる。
… を使用して、配列やオブジェクトを展開して新しい配列やオブジェクトを生成。これにより、配列やオブジェクトの要素やプロパティを柔軟に組み合わせたり変更できる。 pic.twitter.com/cXkwNj3zkw— もりだい@エンジニア挑戦中 (@moridai1104) April 30, 2024
ToDoアイテムの完了状態の切り替え
ReactのToDoアプリ
ToDoアイテムの完了状態の切り替え pic.twitter.com/kc8DAZmCD5— もりだい@エンジニア挑戦中 (@moridai1104) May 2, 2024
const toggleTodo = (id) => {
const newTodos = [...todos];
const todo = newTodos.find((todo) => todo.id === id);
todo.completed = !todo.completed;
setTodos(newTodos);
};
toggleTodo
関数は、ToDoアイテムの完了状態を切り替えるための処理です。
1.const newTodos = [...todos];
newTodos
という新しい配列を作成し、現在のToDoリストtodos
をそのままコピーします。- これにより、元のToDoリストを直接変更せず、新しい配列を操作することができます。
2.const todo = newTodos.find((todo) => todo.id === id);
find
メソッドを使用して、引数で受け取ったid
に一致するToDoアイテムを検索します。id
が一致するToDoアイテムが見つかれば、それをtodo
という変数に格納します。
3.todo.completed = !todo.completed;
todo
オブジェクトのcompleted
プロパティ(完了状態)を反転させます。つまり、完了状態がtrue
ならfalse
に、false
ならtrue
に変更します。
4.setTodos(newTodos);
:
- 更新されたToDoアイテムを含む新しいToDoリスト
newTodos
を使用して、setTodos
関数を呼び出します。 - これにより、ToDoリストの状態が更新され、Reactは自動的にUIを再レンダリングして変更を反映します。
このようにして、toggleTodo
関数は特定のToDoアイテムの完了状態をトグルし、ToDoリストのUIを更新します。
完了したタスクの削除
ReactとToDoアプリ
完了したタスクの削除 pic.twitter.com/0gPA6ua0rj— もりだい@エンジニア挑戦中 (@moridai1104) May 2, 2024
const handleClear = () => {
const newTodos = todos.filter((todo) => !todo.completed);
setTodos(newTodos);
};
1.const newTodos = todos.filter((todo) => !todo.completed);
filter
メソッドを使用して、未完了のToDoアイテムだけをフィルタリングして新しいToDoリストnewTodos
を作成します。todo.completed
がfalse
(未完了)であるToDoアイテムのみがnewTodos
に含まれます。
2.setTodos(newTodos);
- 更新されたToDoリスト
newTodos
を使用して、setTodos
関数を呼び出します。 - これにより、ToDoリストの状態が更新され、Reactは自動的にUIを再レンダリングして変更を反映します。
このようにして、handleClear
関数はToDoリストから完了したToDoアイテムを削除し、ToDoリストのUIを更新します。
ReactのTodoアプリコードを理解-TodoList.js-
import React from "react";
import Todo from "./Todo";
const TodoList = ({ todos, toggleTodo }) => {
return todos.map((todo) => <Todo todo={todo} key={todo.id} toggleTodo={toggleTodo}/>);
};
export default TodoList;
1.import React from "react";
import Todo from "./Todo";
- React モジュールと、後で使用する Todo コンポーネントをインポートしています。
2.const TodoList = ({ todos, toggleTodo }) => {
- TodoList コンポーネントを関数形式で定義しています。引数として、todos と toggleTodo を受け取ります。
- todos はToDoアイテムの配列であり、toggleTodo はToDoアイテムの完了状態を切り替えるための関数です。
3. return todos.map((todo) => <Todo todo={todo} key={todo.id} toggleTodo={toggleTodo}/>);
};
- todos 配列を map() メソッドで反復処理し、各ToDoアイテムを Todo コンポーネントにマップします。
- 各ToDoアイテムに対して
<Todo />
コンポーネントを作成し、todo プロパティと toggleTodo プロパティを渡します。 - key プロパティには、ToDoアイテムの一意のID(todo.id)が使用され、Reactが各アイテムを一意に識別できます。
4.export default TodoList;
- TodoList コンポーネントを他のファイルでインポートできるようにエクスポートします。
このようにして、TodoList コンポーネントは、親コンポーネントから受け取ったToDoリストの各アイテムをマップして、ToDoリスト全体をレンダリングします。各ToDoアイテムは、個別の Todo コンポーネントに渡され、それぞれが個別にレンダリングされます。
ReactのTodoアプリコードを理解-Todo.js-
import React from "react";
const Todo = ({ todo, toggleTodo }) => {
const handleTodoClick = () => {
toggleTodo(todo.id);
};
return (
<div>
<label>
<input type="checkbox" checked={todo.completed} readOnly onChange={handleTodoClick} />
</label>
{todo.name}
</div>
);
};
export default Todo;
1.import React from "react";
- React` モジュールをインポートしています。
2.const Todo = ({ todo, toggleTodo }) => {
- `Todo` コンポーネントをアロー関数形式で定義しています。引数として、`todo` と `toggleTodo` を受け取ります。
- `todo` は個々のToDoアイテムを表し、`toggleTodo` はToDoアイテムの完了状態を切り替えるための関数です。
3.const handleTodoClick = () => {toggleTodo(todo.id);};
- ToDoアイテムがクリックされたときに呼び出される `handleTodoClick` 関数を定義しています。
- この関数は、`toggleTodo` 関数を呼び出して、対象のToDoアイテムの完了状態を切り替えます。
4.<input type="checkbox" checked={todo.completed} readOnly onChange={handleTodoClick} />
- チェックボックスとToDoアイテムの名前を表示する JSX を返しています。
- チェックボックスの `checked` 属性は、ToDoアイテムの `completed` プロパティにバインドされています。
- チェックボックスの状態が変更されたときに呼び出される関数は `handleTodoClick` です。
5.export default Todo;
- `Todo` コンポーネントを他のファイルでインポートできるようにエクスポートします。
このようにして、`Todo` コンポーネントは、ToDoアイテムを表示し、ユーザーがToDoアイテムの完了状態を切り替えるためのUIを提供します。
まとめ
今回は、Reactを使用してToDoアプリを作成する方法について解説しました。Reactを使用することで簡単に作成することができますのでチャレンジしてみてください。
1. プロジェクトのセットアップ
– Reactプロジェクトを作成し、必要なライブラリをインストールします。
– プロジェクト内にコンポーネントを作成し、必要なファイルを準備します。
2. ToDoリストの表示
– ToDoリスト全体を表示する `TodoList` コンポーネントを作成します。
– 各ToDoアイテムを表示する `Todo` コンポーネントも定義します。
3. ToDoアイテムの追加と完了状態の切り替え
– フォームとボタンを使用して、ユーザーがToDoアイテムを追加できるようにします。
– チェックボックスをクリックすることで、ToDoアイテムの完了状態を切り替える機能も実装します。
4. 完了したタスクの削除
– ボタンをクリックすることで、完了したToDoアイテムをリストから削除します。
以上の手順に従うことで、Reactを使用してToDoアプリを作成する基本的な方法を簡潔に解説しました。Reactの基本的な概念と、コンポーネント間のデータの受け渡し方法を理解するための良い練習になります。