Reactでtodoアプリを作ろう③:機能追加

前回まででTodoの追加・表示ができるようになったので
今回は以下2つの便利機能を実装していきます。


①入力フォームの入力内容をクリア
 現状では、Addボタンを押しても入力値がそのままなので
 Addと同時にフォーム内を空にする。

②Todoを削除
 終了したTodoを削除できるようにする。

①入力フォームの入力内容をクリア


入力フォームはFormコンポーネントのStateで管理しているので
「フォーム内を空にする」という状態にStateを変更してあげる必要があります。


なのでAddがクリックされたときにState変更関数を呼び出し、
引数に空("")を渡します。

//Form.jsx

//inputとtextareaの入力フォーム内を空にする関数を定義
 const resetInputField = () => {
    setToDoTitle("");
    setToDoContent("");
  }

//resetInputField関数をcallAddToDoList関数に追加
//callAddToDoList関数はAddボタンがClickされた時に呼び出される関数
  const callAddToDoList = (e) => {
    e.preventDefault();
    props.addToDoList(toDoTitle, toDoContent);
    resetInputField();
  }


これでAddボタンがクリックされた時に入力フォーム内が空になります!


②Todoを削除

ToDoListコンポーネント及びAppコンポーネントに以下の内容を追加します。


●Appコンポーネント
(1)選択されたTodoを削除する関数(deleteToDoList)を定義
(2)deleteToDoList関数をpropsでToDoListコンポーネントに渡す


●ToDoListコンポーネント
(1)toDoListItems関数にDeleteボタンを追加
(2)DeleteボタンにonClickイベント(deleteToDoList)を設定


上記をコードに起こすと....

//App.jsx

//deleteToDoListの定義:Todoを削除する関数
  const deleteToDoList = (index) => {
    setToDoList(toDoList.filter(item => toDoList[index] !== item));
  }

//ToDoListコンポーネントへdeleteToDoListをpropsで渡す
<ToDoList toDoList={toDoList} deleteToDoList={deleteToDoList}/>
//ToDoList.jsx

const toDoListItems = props.toDoList.map(
    (item, index) => {
      return(
        <div key={index} className="card toDo-item">
          <div className="card-body">
            <h5 className="card-title">Title: {item.title}</h5>
            <p className="card-text">Content: {item.content}</p>
        //Deleteボタンの追加とonClickイベントにコールバック関数を渡す
            <button onClick={() => props.deleteToDoList(index)}>
              Delete
            </button>
          </div>
        </div>
      );
    }
  );

filter()メソッドはどのように動いているのか

filter()メソッドについて私の中で理解が浅かったので、まとめてみました。


MDNでは以下のように説明されています。

filter() メソッドは、与えられた関数によって実装されたテストに合格したすべての配列からなる新しい配列を生成します。

developer.mozilla.org

言い換えると、

配列の要素全てに対し、指定した条件でテストを行い、
そのテストに合格した要素だけを取り出し、新しい配列を生成する。

ということでしょうか。

なので、ある条件で要素を絞り込みたい時などに使えるメソッドと言えますね。


今回は

deleteボタンがclickされた要素を削除したい
↓つまり
deleteボタンがclickされた要素以外の要素で新しい配列を作成し、
その新しい配列を描画する(すると、削除されたように見える)

という考え方になります。


関数の中身を見ていくと....

//App.jsx

  const deleteToDoList = (index) => {
    setToDoList(toDoList.filter(item => toDoList[index] !== item));
  }

toDoList(入力されたTodoを保持)に対してfilter()メソッドを指定し
コールバック関数で、絞り込みたい条件を設定しています。

●どんな条件で絞込をしているのか?●
⇒要素の中身を比較している(toDoList[index]とitemの中身)


toDoList[index]の中にはどのような値が入ってくるのかを確認するために
DeleteボタンをClickした際のtoDoList[index]の値をコンソールに表示させてみました。

console.log(toDoList[index]);

すると....

f:id:hnm-n-1029:20200724151505g:plain


要素の中身が表示されていることが分かります。

確かに、toDoList[index]は配列の要素にアクセスする記述です。
そしてこのindexはどこからきているのかというと、
ToDoListコンポーネントからdeleteToDoListへ引数として渡されています。

ToDoList.jsx
//引数にindexを渡している
<button onClick={() => props.deleteToDoList(index)}>


これで削除機能が追加できました。


ということで、hookを使った簡単なTodoアプリの完成です!

今回は以上なります!


↓↓私の師匠、もりけんさんの武骨日記。問題集、要チェック

kenjimorita.jp