【初心者向け】Reactを使ったTodoアプリの作り方を解説

サムネイル
               

Reactを勉強するためにYouTubeでTodoアプリの作成したけど、全く理解できない。

 

今回はReactの知識ゼロの筆者がわかりやすくTodoアプリのコードを解説していきます。

↓↓↓参考にして作ったYouTube↓↓↓

 

Todoアプリの動作を簡単にまとめ

1.ToDoアイテムの管理

ユーザーが入力したToDoアイテムはリストで管理。

2.ToDoアイテムの追加

ユーザーが新しいToDoアイテムを入力すると、それがリストに追加。

3.ToDoアイテムの完了マーク

ユーザーがToDoアイテムをクリックすると、そのアイテムが完了したことにマークされる。

4.完了したToDoアイテムの削除

ユーザーが削除ボタンをクリックすると、完了したToDoアイテムがリストから削除。

 

これらの操作は、状態変数todosと更新関数setTodosを使用してReactコンポーネント内で処理されます。そして、これによってToDoリストはユーザーの入力や操作に応じて動的に変化し、リアルタイムで表示が更新されます。

 

ファイル構造を視覚化

コードを視覚的に理解しやすくするために、コンポーネント間の関係を示す簡単な設計図です。以下のような構造を持つReactアプリケーションになります。

 

一つずつそれぞれのファイルについて説明していきます。

 

App
├─ TodoList
│ └─ Todo (複数)
└─ フォームとボタン

react-todolist

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;

moridai
moridai
App.jsは大きく5つのセクションに分かれています。

 

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アイテムの名前を入力するための参照を提供します。

 

moridai
moridai
Reactフックについて解説したツイートも参考にしてください!

 

 

 

 

ToDoアイテムの追加

 

  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アイテムを追加し、入力フィールドをクリアするという機能を持ちます。

     

     

     

    ToDoアイテムの完了状態の切り替え

     

      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を更新します。

     

     

     

    完了したタスクの削除

     

      const handleClear = () => {
        const newTodos = todos.filter((todo) => !todo.completed);
        setTodos(newTodos);
      };

     

    1.const newTodos = todos.filter((todo) => !todo.completed);

    • filter メソッドを使用して、未完了のToDoアイテムだけをフィルタリングして新しいToDoリスト newTodos を作成します。
    • todo.completedfalse(未完了)である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の基本的な概念と、コンポーネント間のデータの受け渡し方法を理解するための良い練習になります。