Reactを使ったTODOアプリ制作

この記事ではReactを使ったTODOアプリ制作の過程をアウトプット目的で記録していく。
なお、このアプリはUdemyの動画教材をもとに作成したものであり、オリジナルではありません。
>利用したUdemyの動画はこちら。
>
https://www.udemy.com/share/103Fxl3@DFqXSjmdcc7_Y3AJBXUjpYfQxm89A21iB9khusee6vv4M8gH-_BurBoaBUk2OQVvSA==/

## 制作するTODOアプリ概要
以下の画像のようなWebアプリを制作していく。

### 画面構成
・TODOを追加するエリア
・未完了のTODOエリア
・完了のTODOエリア

### 機能
・「追加」すると未完了のTODOに格納され、「完了」すると完了のTODOに移動する。
・「削除」すると未完了のTODOから削除され、「戻す」と未完了のTODOに移動する。
・TODO上限は5つまでとし、上限に達した場合はタスクを消化するよう警告が表示される。

![スクリーンショット 2024-09-17 11.45.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/d66a0321-c679-4de4-332b-dd3b4dc3dbe2.png)

## ディレクトリ構成
初期段階のsrcフォルダには3つのファイルが格納されている。
・Todo.jsx
・index.jsx
・style.css

## コーディング開始
### 流れ
1\. Todo.jsxにマークアップを記述
2\. style.cssにスタイルを記述
3\. 未完了のTODOを`state`を意識したマークアップに改善
4\. 完了のTODOを`state`を意識したマークアップに改善
5\.タスクの追加機能の実装
6\.タスクの削除機能の実装
7\.タスクの完了機能の実装
8\.タスクの戻す機能の実装
9\.`state`の初期値を削除する
10\.コンポーネント化する
11\.各コンポーネントに該当するcssのスタイルもコンポーネントで分ける
12\.Todoの上限設定

### 1\. Todo.jsxにマークアップを記述
マークアップはJSX記法に基づいて行なっていく。
最終的にはコンポーネントを使ってTODOの内容を表現するが、現段階では未完了のTODOと完了のTODOにそれぞれ仮のTODOを表示させておく。
```Todo.jsx
import "./style.css";

export const Todo = () => {
    return (
        <>
          <div>
              <input placeholder="TODOを入力" />
              <button>追加</button>
          </div>
          <div>
              <p>未完了のTODO</p>
              <ul>
                  <li>
                      <div>
                          <p>これからTODO</p>
                          <button>完了</button>
                          <button>削除</button>
                      </div>
                  </li>
                  <li>
                      <div>
                          <p>これからTODO</p>
                          <button>完了</button>
                          <button>削除</button>
                      </div>
                  </li>
              </ul>
        　</div>
          <div>
              <p>完了のTODO</p>
              <ul>
                  <li>
                      <div>
                          <p>終わったTODO</p>
                          <button>戻す</button>
                      </div>   
                  </li>
                  <li>
                      <div>
                          <p>終わったTODO</p>
                          <button>戻す</button>
                      </div>
                  </li>
              </ul>
          </div>
        </>
    );
};
```
### 2\. style.cssにスタイルを記述
最終的にスタイルはコンポーネントごとに記述を分けることになるが、現段階では全てstyle.cssに記述していく。
全ての要素に共通するスタイルは、このままstyle.cssに残ることになる。
```style.css
body {
  font-family: sans-serif;
  color: #555;
  font-weight: bold;
}

input {
  border-radius: 8px;
  border: none;
  padding: 8px 16px;
  margin-right: 5px;
}

button {
  border-radius: 8px;
  border: none;
  padding: 4px 16px;
  margin: 0px 2px;
}

button:hover {
  background-color: #79a8a9;
  color: #fff;
  cursor: pointer;
}

.input-area {
  background-color: #c6e5d9;
  width: 400px;
  height: 30px;
  padding: 8px;
  margin: 8px;
  border-radius: 8px;
} 

.incomplete-area {
  border: solid 2px #79a8a9;
  border-radius: 8px;
  width: 400px;
  min-height: 200px;
  padding: 8px;
  margin: 8px;
}

.complete-area {
  border: solid 2px #79a8a9;
  background-color: #c6e5d9;
  border-radius: 8px;
  width: 400px;
  min-height: 200px;
  padding: 8px;
  margin: 8px;
}

.title {
  text-align: center;
  margin-top: 0;
  font-weight: bold;
}

.list-row {
  display: flex;
  align-items: center;
}

.todo-item {
  margin: 6px;
}

```
スタイルの適用に伴って、Todo.jsxに`class`を追加する。
```Todo.jsx
import "./style.css";

export const Todo = () => {
    return (
        <>
          <div className="input-area">
              <input placeholder="TODOを入力" />
              <button>追加</button>
          </div>
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                  <li>
                      <div className="list-row">
                          <p className="todo-item">これからTODO</p>
                          <button>完了</button>
                          <button>削除</button>
                      </div>
                  </li>
                  <li>
                      <div className="list-row">
                          <p className="todo-item">これからTODO</p>
                          <button>完了</button>
                          <button>削除</button>
                      </div>
                  </li>
              </ul>
        　</div>
          <div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  <li>
                      <div className="list-row">
                          <p className="todo-item">終わったTODO</p>
                          <button>戻す</button>
                      </div>   
                  </li>
                  <li>
                      <div className="list-row">
                          <p className="todo-item">終わったTODO</p>
                          <button>戻す</button>
                      </div>
                  </li>
              </ul>
          </div>
        </>
    );
};
```

### 3\. 未完了のTODOを`state`を意識したマークアップに改善
未完了のTODOと完了のTODOのエリアは常に状態が変化していく要素となる。
**状態**なので`state`で管理することになるため、それに合わせたマークアップにしていく。

#### 未完了のTODO一覧を`state`で定義する
未完了のTODOは複数の要素となるので配列として定義する。
この時`state`の定義には`useState`を用いることを忘れずに。
>`useState`についてはこちら
>
https://qiita.com/naoki-atjp/items/d43d4dd542ee88b83a2c#state%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

今回`useState`には`inCompleteTodos`とセット関数`setIncompleteTodos`を配列に用意。
`useState`の初期値には仮の配列として`これからTODO1`と`これからTODO2`を設定。
`useState`のAuto importも忘れずに。
```Todo.jsx
import {useState} from "react";
import "./style.css";

export const Todo = () => {
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    return (
        <>
            //省略
        </>
    );
};
```
#### `state`をもとに`map`メソッドを使って`li`タグ部分を表示する
具体的には、配列の`state`をもとに画面の要素を一覧で出していく部分をループしながらレンダリングしていく。
Reactでの一覧表示は、配列を`map`でループしながら一つずつ新しい要素を返却することで行う。

`map`はメソッドなので関数(アロー関数)形式で記述し、引数に**ループする各要素**が入る。
返却するのは`li`タグの中身なので、`li`タグ部分を丸々関数の中にコピペする。

`p`タグの中身を`map`メソッドの引数に修正し、最終的なコードは以下のようになる。
```Todo.jsx
import {useState} from "react";
import "./style.css";

export const Todo = () => {
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    return (
        <>
         //省略
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo) => {
                    return (
                        <li>
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button>完了</button>
                                <button>削除</button>
                            </div>
                        </li>                    
                    );
                })};
              </ul>
        　</div>
          //省略
        </>
    );
};
```
>`map`メソッドについてはこちら
>
https://qiita.com/naoki-atjp/items/e61d63a082cd0bf5e0c6#8map%E3%81%A8filter%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E9%85%8D%E5%88%97%E3%81%AE%E5%87%A6%E7%90%86

#### `key`を設定する
`map`や`filter`において、配列の値をもとに一覧表示をする時には、`key`の設定が必要となる。
`key`設定は配列をループして`return`している一番上の要素に行い、今回は`return`直下の`li`タグが該当する。
例えば`<li key={todo}>`のように設定する。

##### なぜ`key`が必要なのか
Reactの仮想DOMは変更前と変更後の差分だけ抽出して、その差分のみ実際のDOMに反映していく。
そのため今回のようにループでレンダリングする場合、何個目の要素なのかを正確に比較するために目印をつけてあげる必要がある。
それでループしている各要素の一意になる項目を`key`に設定することとなる。

#### アロー関数の特性を活かして`{}`と`return`を省略する
今回`return`の中身がひとまとまりとなっているので、アロー関数の省略記法を用いて記述を簡潔にしていく。
```Todo.jsx
//省略

export const Todo = () => {
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    return (
        <>
         //省略
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo) => (
                        <li　key={todo}>  //keyの設定
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button>完了</button>
                                <button>削除</button>
                            </div>
                        </li>                    
                    ))}
              </ul>
        　</div>
          //省略
        </>
    );
};
```

### 4\. 完了のTODOを`state`を意識したマークアップに改善
未完了のTODOと同様の流れで完了のTODOを`state`で管理する記述に修正していく。
```Todo.jsx
//省略

export const Todo = () => {
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    return (
        <>
         //省略
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo) => (
                        <li　key={todo}>  //keyの設定
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button>完了</button>
                                <button>削除</button>
                            </div>
                        </li>                    
                    ))}
              </ul>
        　</div>
        　<div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  {completeTodos.map((todo) => (
                            <li key={todo}>
                              <div className="list-row">
                                  <p className="todo-item">{todo}</p>
                                  <button>戻す</button>
                              </div>   
                            </li>
                      ))}
              </ul>
          </div>
        </>
    );
};
```

### 5\.タスクの追加機能の実装
テキストボックスに入力した内容を、追加ボタンを押したら未完了のTODOに追加されるように機能を実装していく。
イメージは以下の通り
- `input`に入力した内容を取得する
- それを`inCompleteTodos`の配列の中に追加する
- すると`map`のループによって自動的に表示される

この時「入力された状態はなんなのか」という**状態**を管理するため`state`を用いる。
新しく以下の`useState`の記述を追加する。
`state`名は`todoText`、更新関数は`setTodoText`とし、初期値には空文字を定義しておく。
```Todo.jsx
export const Todo = () => {
    const [todoText, setTodoText] = useState(""); //追加
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    return ( //省略
```

この入力された内容、すなわち`todoText`という値は`input`における`vale`に当たるので、`value`属性に`todoText`を設定しておく。
```Todo.jsx
export const Todo = () => {
    const [todoText, setTodoText] = useState(""); //追加
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    return ( 
            <>
              <div className="input-area">
                  <input placeholder="TODOを入力" value={todoText} /> //属性を追加
                  <button>追加</button>
              </div>
             //省略
```
例えばこの状態で`useState`の初期値に`test`と入力すると、画面の`input`部分には「test」 と表示されるようになる。
しかし、表示画面からテキストボックスに直接入力しようとしても入力できない状態になっている。
これは、初期値が空文字に設定していて、その値を常にvalueに設定しているので常に空文字状態になってしまっていることが原因。

解決方法として、テキストボックスにユーザーが変更を加えたことを検知して、それをもとに常に`todoText`の`state`を更新するという処理を実装する。

#### `input`の入力内容の変更を検知させる
`input`の入力内容を自動で検知するには`onChange`イベントを用いる。
`onChange`はテキストボックスに変更があったときに実行されるイベント。

- `input`タグ内にイベントを追加
`<input placeholder="TODOを入力" value={todoText} onChange={} />`
- `onChange`が実行された時の関数を定義
`onChangeTodoText`という名前で定義するので、その関数を`onChange`イベントで呼び出す。
`<input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />`
- 関数の中身を入力された内容を検知するように記述
このようなイベントは自動で`event`という引数が渡ってくる。
そして、`setTodoText`の`event`の`target`の`value`というところに入力された文字が入ってくるように関数を書く。


```Todo.jsx
export const Todo = () => {
    //省略
    const onChageTodoText = (event) => setTodoText(event.target.value);
    
    return ( 
            <>
              <div className="input-area">
                  <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
                  <button>追加</button>
              </div>
             //省略
```
結果として`input`に値が入力されると`onChange`イベントが発火し、その内容をもとに`todoText`の`state`を更新して、その`todoText`の値が`value`に常に設定されるという流れを作ることができた。
`input`に入力された値と`todoText`の`state`の値が常にイコール状態を保てる状態になったので、入力した値が`value'となって画面に表示される。

#### 追加ボタンを押した時の処理を作る
- `button`タグにクリックイベントを割り当てる。
- そしてイベントが発火した時の関数として`onClickAdd`という関数を定義する。
```Todo.jsx
export const Todo = () => {
    const [todoText, setTodoText] = useState(""); //追加
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        
    };
    
    return ( 
            <>
              <div className="input-area">
                  <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
                  <button onClick={onClickAdd}>追加</button>
              </div>
             //省略
```
- テキストボックスに入力された内容を`inCompleteTodo`の配列に追加する
配列に追加する、つまり配列の結合なのでスプレッド構文を使用する。

まず追加した新しい配列を格納する関数を`newTodos`として用意する。
そして新しい配列を生成したいので、スプレッド構文を使って現在の`inCompleteTodos`を配列で設定。
(`inCompleteTodos`の配列のコピーを`newTodos`として生成)
```Todo.jsx
export const Todo = () => {
    const [todoText, setTodoText] = useState(""); //追加
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        const newTodos = [...inCompleteTodos];
    };
    
    return ( 
            <>
              <div className="input-area">
                  <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
                  <button onClick={onClickAdd}>追加</button>
              </div>
             //省略
```
>スプレッド構文についてはこちら
>
https://qiita.com/naoki-atjp/items/e61d63a082cd0bf5e0c6#7%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%A7%8B%E6%96%87

`newTodos`にコピーした配列に追加したい要素は`todoText`の値なので、`newTodos`の配列に追記する。
`const newTodos = [...inCompleteTodos, todoText];`

そして、新しい要素が追加された配列`newTodos`を更新される値、つまり`setInCompleteTodos`に渡せば現在の状態に新たな配列が追加された状態になる。
```Todo.jsx
export const Todo = () => {
    const [todoText, setTodoText] = useState(""); //追加
    const [inCompleteTodos, setInCompleteTodos] = useState(["これからTODO1", "これからTODO2"]);
    const [completeTodos, setCompleteTodos] = useState(["終わったTODO1", "終わったTODO2"]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
    };
    
    return ( 
            <>
              <div className="input-area">
                  <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
                  <button onClick={onClickAdd}>追加</button>
              </div>
             //省略
```
この段階で、テキストボックスに入力した内容を追加ボタンをクリックすることで未完了のTODOに追加することができるようになった。

#### 追加した時にテキストボックスの入力を空にする
これは簡単で、`setInCompleteTodoText`に`newTodos`を渡した後に、`setTodoText`に空文字を渡すだけで処理が完了する。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickAdd = () => {
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); //空文字を設定
    };
          //省略
```
また、現在の状態では何も入力してない時に追加ボタンをクリックすると、空のTODOが追加されてしまうので、その問題を条件式で解消する。

#### `todoText`が空の時は`return`させる
テキストボックスが状態では追加できないように条件式を記述する。
これで空文字の時はif文の行で`return`されるためそこで処理が止まり、その下の配列の追加処理は行われなくなるため、空文字のTODOは追加できなくなった。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); //空文字を設定
    };
          //省略
```

### 6\.タスクの削除機能の実装
削除ボタンにクリックイベントを付与し、削除ボタンが押されたときに、押された対象の行の`completeTodos`の要素を削除するという流れの機能になる。

#### イベントを用意し関数を定義する
イベントで呼び出す関数名は`onCkickDelete`とする。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = () => {}
    return ( 
        <>
          <div className="input-area">
              <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
              <button onClick={onClickAdd}>追加</button>
          </div>
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo) => (
                        <li key={todo}>  
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button>完了</button>
                                <button onClick={onClickDelete}>削除</button>
                            </div>
                        </li>                    
                    ))}
              </ul>
        　 </div>
```

#### 削除されたのが配列の何番目かを取得する
現在`map`の部分には何番目かを判定する要素がないので、それを追加していく。
`map`の第二引数には`index`が入ってくるのでこれを活用する。
`index`は0番目のループ、1番目のループというようにインデックス番号を表す引数。

`map`の第二引数に`index`を渡し、`onClickDelete`関数の引数にも`index`を渡すことで、`onClickDelete`は`index`を引数として受け取る関数になる。
そして試しに`alert`で`index`の値が表示されるようにし、イベントの引数にも`index`を持たせることでアラートを実装する。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = (index) => {
        alet(index);
    }
    return ( 
        <>
          <div className="input-area">
              <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
              <button onClick={onClickAdd}>追加</button>
          </div>
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo, index) => (
                        <li key={todo}>  
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button>完了</button>
                                <button onClick={onClickDelete(index)}>削除</button>
                            </div>
                        </li>                    
                    ))}
              </ul>
        　 </div>
```
すると常にアラートが表示されるという、アラートが暴走するバグが発生してしまう。
原因は、イベント部分を`{}`で記述しているためJSとして解釈されてしまい、ループでその部分を通るたびに関数が実行されてしまっているから。

それでJSX記法をしている部分から引数を設定した関数を実行したときは、`{}`の中に関数を生成してあげる。
`<button onClick={() => onClickDelete(index)}>削除</button>`
そうすることで`{}`の中身は関数としてではなく、関数を実行した時の処理として認識されるようになる。
すなわち、イベントが発火した時に`onClickDelete`が即時実行されることがなくなったので、アラートの暴走が止まる。

この状態で未完了のTODOにあるリストの削除ボタンをクリックすると、アラートで`index`の値が正常に表示されるようになる。

#### 取得した`index`をもとに`inCompleteTodos`からn番目の値を削除する処理を実装
削除した後の新しい配列を取得したいので、追加の時と同様に`newTodos`という関数を用意。
そしてスプレッド構文を用いて'newTodos'に今の未完了リストの一覧、すなわち`inCompleteTodos`をコピーした配列を用意する。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
    }
    return ( 
        //省略
```
- コピーした配列に対して`index`番目の要素を削除する機能を実装
JSの`splice`メソッドを使う。
`splice`は第一引数に`index`、第二引数に`1`を指定することで、何番目の`index`の要素から1個削除するという処理になる。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
    }
    return ( 
        //省略
```
上記の記述だと、`onClickDelete`の引数`index`が0番目だとしたら、0番目の要素から1個削除するという機能になっている。
つまり0番目の要素だけ削除することがでできる。

最後に`setInCompleteTodos`に`newTodos`を渡せばいよい。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }
    return ( 
        //省略
```
これで、新しいTODOの追加と削除ボタンの機能の実装が完了した。

### 7\.タスクの完了機能の実装
未完了のTODOの完了ボタンをクリックすると、完了のTODOに移動する処理を実装していく。
完了ボタンも削除ボタンと同様に「何番目の要素を」という考え方を使うので、削除ボタンのクリックイベントと同じ方で実装することができる。

関数名は`onClickComplete`とし引数に`index`を持たせる。
そして削除ボタンと同様に関数を定義し、引数に`index`を持たせておく。
- 完了を押したら未完了TODOから削除する
- 完了を押したら完了TODOの一番下に追加する

という処理が必要になるので、順に行っていく。
#### 未完了TODOから削除する
削除の部分は`onClickDelete`関数の上2行をコピペする。
ただし変数の名前だけ、今回は完了したTODOも対象になってくるので`newTodos`ではなく`newInCompleteTodos`としておく。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }
    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)
    }
    return ( 
        //省略
            <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo, index) => (
                        <li key={todo}>  
                            <div className="list-row">
                                <p className="todo-item">{todo}</p>
                                <button onClick={() => onClickComplete(index)}>完了</button>
                                <button onClick={() => onClickDelete(index)}>削除</button>
                            </div>
                        </li>                    
                    ))}
              </ul>
        　 </div>
```
後は`state`を更新すれば完了ボタンを押した時に未完了TODOから削除されるようになる。
その前に完了TODOに追加する機能を実装する。

#### 完了TODOに追加する
配列の`state`を更新していくので新しく`newCompleteTodos`という新しい完了TODOの一覧の`state`を用意する。
これも既存の完了TODOの配列(`completeTodos`)に、完了ボタンが押された行の要素を追加することになるので、スプレッド構文でこれまでと同じように実装していく。

完了ボタンが押された行の要素の取得は`inCompleteTodos`の`index`を取得すれば良いので、以下のような記述になっていく。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)
    }

    const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; //ここを追加
    return ( 
        //省略
```
これで新しい完了TODOの一覧もできたので、未完了TODO(`setInCompleteTodos`)と完了TODO(`setCompleteTodos`)のそれぞれの`state`を更新していく。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    return ( 
        //省略
```
これで、タスクの追加・削除・完了の機能の実装ができた。

### 8\.タスクの戻す機能の実装
完了ボタンの逆の流れを行う。
まずは`map`の第二引数に`index`を渡し、イベントの記述、`onClickBack`という関数を用意する。
```Todo.jsx
export const Todo = () => {
    //省略
    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }

    const onClickBack = (index) => {
        
    }
    
    return ( 
        //省略
            <div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  {completeTodos.map((todo, index) => (
                        <li key={todo}>
                              <div className="list-row">
                                  <p className="todo-item">{todo}</p>
                                  <button onClicK={() => onClickBack(index)}>戻す</button>
                              </div>   
                        </li>
                  ))}
              </ul>
          </div>
        </>
```
処理としては以下の通りなので順に行っていく
- 戻すボタンを押すと完了TODOから削除される
- 戻すボタンを押すと未完了TODOの一番下に追加される

#### 戻すボタンを押すと完了TODOから削除される
```Todo.jsx
export const Todo = () => {
    //省略
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);
    }
    
    return ( 
        //省略
```
#### 戻すボタンを押すと未完了TODOの一番下に追加される
追加の処理を記述し、最後にそれぞれの`state`を更新する。
```Todo.jsx
export const Todo = () => {
    //省略
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        //省略
```

### 9\.`state`の初期値を削除する
TODOアプリに必要なすべての機能の実装ができたので、初期値として入れていた値を削除する。
最終的なコードは以下の通り。
```Todo.jsx
import {useState} from "react";
import "./style.css";

export const Todo = () => {
    const [todoText, setTodoText] = useState("");
    const [inCompleteTodos, setInCompleteTodos] = useState([]);
    const [completeTodos, setCompleteTodos] = useState([]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); 
    };

    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }

    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        <>
          <div className="input-area">
              <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
              <button onClick={onClickAdd}>追加</button>
          </div>
          <div className="incomplete-area">
              <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo, index) => (
                    <li key={todo}>  
                        <div className="list-row">
                            <p className="todo-item">{todo}</p>
                            <button onClick={() => onClickComplete(index)}>完了</button>
                            <button onClick={() => onClickDelete(index)}>削除</button>
                        </div>
                    </li>                    
                ))}
              </ul>
        　 </div>
           <div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  {completeTodos.map((todo, index) => (
                        <li key={todo}>
                              <div className="list-row">
                                  <p className="todo-item">{todo}</p>
                                  <button onClicK={() => onClickBack(index)}>戻す</button>
                              </div>   
                        </li>
                  ))}
              </ul>
          </div>
        </>
    );
};
```

### 10\.コンポーネント化する
現在「入力エリア」「未完了エリア」「完了エリア」が同じファイルに記述されているので、これをコンポーネントで分割して可読性を向上する。

---
- 入力エリア
#### ディレクトリを追加
srcフォルダ配下に新しく`components`というフォルダを作り、さらにその配下に「入力エリア」用の`InputTodo.jsx`というファイルを作成。

#### 関数コンポーネントを記述
`export`と関数コンポーネント`InputoTodo`を用意したら、Todo.jsxから該当部分を切り取って関数の中にペーストする。
``` InputTodo.jsx
export const InputTodo = () => {
    return (
        <div className="input-area">
            <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
            <button onClick={onClickAdd}>追加</button>
        </div>
    )
}
```
この状態だと`todoText`や`onChageText`などの変数や関数が同ファイル内に存在しないのでエラーになっている。
そのため`props`で受け取ったものを参照できるようにリファクタリングしていく。

#### `props`を受け取るようリファクタリング
`props`を受け取る側であるInputTodo.jsxの関数コンポーネントの引数に`props`を渡す。
``` InputTodo.jsx
export const InputTodo = (props) => {
    return (
        <div className="input-area">
            <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText} />
            <button onClick={onClickAdd}>追加</button>
        </div>
    )
}
```
そして呼び出し側のTodo.jsxでは切り取った部分にコンポーネントを呼び出し、Auto importでインポートしておく。

さらに関数もファイル内に存在していないためエラーが吐かれている。
この辺りも`props`で渡していく。
具体的には以下の3つをそれぞれTodo.jsx側で`props`で渡していく。
- `todoText`
- `onChangeTodoText`
- `onClickAdd`

まず`InputTodo`コンポーネントの部分で、`todoText`という`props`名で`todoText`を渡す。
同様に`onChangeTodoText`は省略して`onChange`、`onClickAdd`は省略して`onClick`という`props`名で、それぞれ呼び出す関数を渡していく。
```Todo.jsx
import {useState} from "react";
import {InputTodo} from "./components/InpotTodo";
import "./style.css";

export const Todo = () => {
    const [todoText, setTodoText] = useState("");
    const [inCompleteTodos, setInCompleteTodos] = useState([]);
    const [completeTodos, setCompleteTodos] = useState([]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); 
    };

    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }

    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        <>
          <InputTodo todoText={todoText} onChange={onChageTodoText} onClick={onClickAdd} />
        　//省略
        </>
    );
};
```
これで呼び出し側のコードが完成したので、次はコンポーネント側で渡された`props`を使えるようにリファクタリングしていく。

#### `props`を使えるようにリファクタリング
オブジェクトの分割代入で、`todoText`,`onChange`,`onClick`の3つの`props`を取り出す。
そして名前を変えて`props`を使った部分に合わせて、InputTodo.jsxの変数や関数名を修正する。
``` InputTodo.jsx
export const InputTodo = (props) => {
    const {todoText, onChange, onClick} = props;
    return (
        <div className="input-area">
            <input placeholder="TODOを入力" value={todoText} onChange={onChange} />　//元はonChangeTodoText
            <button onClick={onClick}>追加</button> //元はonClickAdd
        </div>
    )
}
```
これでコンポーネントが完成。

---
- 未完了エリア
#### ディレクトリを追加
`InCompleteTodos.jsx`というファイルを作成。

#### 関数コンポーネントを記述
`export`と関数コンポーネント`InCompleteTodos`を用意したら、Todo.jsxから該当部分を切り取って関数の中にペーストする。
``` InCompleteTodos.jsx
export const InCompleteTodos = () => {
    return (
        <div className="incomplete-area">
            <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo, index) => (
                    <li key={todo}>  
                        <div className="list-row">
                            <p className="todo-item">{todo}</p>
                            <button onClick={() => onClickComplete(index)}>完了</button>
                            <button onClick={() => onClickDelete(index)}>削除</button>
                        </div>
                    </li>                    
                ))}
              </ul>
        　 </div>
    )
}
```
この状態だと`inCompleteTodos`や`onClickComplete`などの変数や関数が同ファイル内に存在しないのでエラーになっている。
そのため`props`で受け取ったものを参照できるようにリファクタリングしていく。

#### `props`を受け取るようリファクタリング
`props`を受け取る側であるInCompleteTodos.jsxの関数コンポーネントの引数に`props`を渡す。
``` InCompleteTodos.jsx
export const InCompleteTodos = (props) => {
    return (
        <div className="incomplete-area">
            <p className="title">未完了のTODO</p>
              <ul>
                {inCompleteTodos.map((todo, index) => (
                    <li key={todo}>  
                        <div className="list-row">
                            <p className="todo-item">{todo}</p>
                            <button onClick={() => onClickComplete(index)}>完了</button>
                            <button onClick={() => onClickDelete(index)}>削除</button>
                        </div>
                    </li>                    
                ))}
              </ul>
        　 </div>
    )
}
```
そして呼び出し側のTodo.jsxでは切り取った部分にコンポーネントを呼び出し、Auto importでインポートしておく。

さらに関数もファイル内に存在していないためエラーが吐かれている。
この辺りも`props`で渡していく。
具体的には以下の3つをそれぞれTodo.jsx側で`props`で渡していく。
- `inCompleteTodos`
- `onClickComplete`
- `onClickDelete`

```Todo.jsx
import {useState} from "react";
import {InputTodo} from "./components/InpotTodo";
import {InCompleteTodos} from "./components/InCompleteTodos";
import "./style.css";

export const Todo = () => {
    const [todoText, setTodoText] = useState("");
    const [inCompleteTodos, setInCompleteTodos] = useState([]);
    const [completeTodos, setCompleteTodos] = useState([]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); 
    };

    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }

    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        <>
          <InputTodo todoText={todoText} onChange={onChageTodoText} onClick={onClickAdd} />
          <InCompleteTodos todos={inCompleteTodos} onCkickComplete={onCkickComplete} onCkickDelete={onCkickDelete} /> 
        　//省略
        </>
    );
};
```
これで呼び出し側のコードが完成したので、次はコンポーネント側で渡された`props`を使えるようにリファクタリングしていく。

#### `props`を使えるようにリファクタリング
オブジェクトの分割代入で、`todos`,`onCkickComplet`,`onCkickDelete`の3つの`props`を取り出す。
そして名前を変えて`props`を使った部分に合わせて、InCompleteTodos.jsxの変数や関数名を修正する。
``` InCompleteTodos.jsx
export const InputTodo = (props) => {
    const {todos, onCkickComplet, onCkickDelete} = props;
    return (
        <div className="incomplete-area">
            <p className="title">未完了のTODO</p>
              <ul>
                {todos.map((todo, index) => (
                    <li key={todo}>  
                        <div className="list-row">
                            <p className="todo-item">{todo}</p>
                            <button onClick={() => onClickComplete(index)}>完了</button>
                            <button onClick={() => onClickDelete(index)}>削除</button>
                        </div>
                    </li>                    
                ))}
              </ul>
        　 </div>
    )
}
```
これでコンポーネントが完成。

---
- 完了エリア
#### ディレクトリを追加
`CompleteTodos.jsx`というファイルを作成。

#### 関数コンポーネントを記述
`export`と関数コンポーネント`CompleteTodos`を用意したら、Todo.jsxから該当部分を切り取って関数の中にペーストする。
``` CompleteTodos.jsx
export const CompleteTodos = () => {
    return (
         <div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  {completeTodos.map((todo, index) => (
                        <li key={todo}>
                              <div className="list-row">
                                  <p className="todo-item">{todo}</p>
                                  <button onClicK={() => onClickBack(index)}>戻す</button>
                              </div>   
                        </li>
                  ))}
              </ul>
          </div>
    )
}
```
この状態だと`CompleteTodos`や`onClickBack`の変数や関数が同ファイル内に存在しないのでエラーになっている。
そのため`props`で受け取ったものを参照できるようにリファクタリングしていく。

#### `props`を受け取るようリファクタリング
`props`を受け取る側であるInCompleteTodos.jsxの関数コンポーネントの引数に`props`を渡す。
``` CompleteTodos.jsx
export const CompleteTodos = (props) => {
    return (
         <div className="complete-area">
              <p className="title">完了のTODO</p>
              <ul>
                  {completeTodos.map((todo, index) => (
                        <li key={todo}>
                              <div className="list-row">
                                  <p className="todo-item">{todo}</p>
                                  <button onClicK={() => onClickBack(index)}>戻す</button>
                              </div>   
                        </li>
                  ))}
              </ul>
          </div>
    )
}
```
そして呼び出し側のTodo.jsxでは切り取った部分にコンポーネントを呼び出し、Auto importでインポートしておく。

さらに関数もファイル内に存在していないためエラーが吐かれている。
この辺りも`props`で渡していく。
具体的には以下の3つをそれぞれTodo.jsx側で`props`で渡していく。
- `CompleteTodos`
- `onClickBack`

```Todo.jsx
import {useState} from "react";
import {InputTodo} from "./components/InpotTodo";
import {InCompleteTodos} from "./components/InCompleteTodos";
import {CompleteTOdos} form "./components/CompleteTodos";
import "./style.css";

export const Todo = () => {
    const [todoText, setTodoText] = useState("");
    const [inCompleteTodos, setInCompleteTodos] = useState([]);
    const [completeTodos, setCompleteTodos] = useState([]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); 
    };

    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }

    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        <>
          <InputTodo todoText={todoText} onChange={onChageTodoText} onClick={onClickAdd} />
          <InCompleteTodos todos={inCompleteTodos} onCkickComplete={onCkickComplete} onCkickDelete={onCkickDelete} /> 
          <CompleteTodos todos={CompleteTodos} onClickBack={onClickBack} />
        </>
    );
};
```
これで呼び出し側のコードが完成したので、次はコンポーネント側で渡された`props`を使えるようにリファクタリングしていく。

#### `props`を使えるようにリファクタリング
オブジェクトの分割代入で、`todos`,`onBack`の2つの`props`を取り出す。
そして名前を変えて`props`を使った部分に合わせて、CompleteTodos.jsxの変数や関数名を修正する。
``` CompleteTodos.jsx
export const InputTodo = (props) => {
    const {todos, onCkickBack = props;
    return (
        <div className="incomplete-area">
            <p className="title">未完了のTODO</p>
              <ul>
                {todos.map((todo, index) => (
                    <li key={todo}>  
                        <div className="list-row">
                            <p className="todo-item">{todo}</p>
                            <button onClick={() => onClickComplete(index)}>完了</button>
                            <button onClick={() => onClickDelete(index)}>削除</button>
                        </div>
                    </li>                    
                ))}
              </ul>
        　 </div>
    )
}
```
これでコンポーネントが完成。

####最終的なTodo.jsx
親コンポーネントの`App`の`return`の中身が3つのコンポーネントのエリアに分かれていて、各コンポーネントの役割が名前からわかる用の異なった。
さらにコンポーネントしておくことによって、使いまわしたいときに１行のコピペだけで済むようになった。

```Todo.jsx
import {useState} from "react";
import {InputTodo} from "./components/InpotTodo";
import {InCompleteTodos} from "./components/InCompleteTodos";
import {CompleteTOdos} form "./components/CompleteTodos";
import "./style.css";

export const Todo = () => {
    const [todoText, setTodoText] = useState("");
    const [inCompleteTodos, setInCompleteTodos] = useState([]);
    const [completeTodos, setCompleteTodos] = useState([]);
    
    const onChageTodoText = (event) => setTodoText(event.target.value);

    const onClickAdd = () => {
        if (todoText === "") return;
        const newTodos = [...inCompleteTodos, todoText];
        setInCompleteTodoText(newTodos);
        setTodoText(""); 
    };

    const onClickDelete = (index) => {
        const newTodos = [...inCompleteTodos];
        newTodos.splice(index, 1)
        setInCompleteTodos(newTodos);
    }

    const onClickComplete = (index) => {
        const newInCompleteTodos = [...inCompleteTodos];
        newInCompleteTodos.splice(index, 1)

        const newCompleteTodos = [...completeTodos, inCompleteTodos[index]]; 
        setInCompleteTodos(newInCompleteTodos);
        setCompleteTodos(newCompleteTodos);
    }
    
    const onClickBack = (index) => {
        const newCompleteTodos = [...completeTodos];
        newCompleteTodos.splice(index, 1);

        const newInCompleteTodos = [...inCompleteTodos, completeTodos(index)];
        setCompleteTodos(newCompleteTodos);
        setInCompleteTodos(newInCompleteTodos);
    }
    
    return ( 
        <>
          <InputTodo todoText={todoText} onChange={onChageTodoText} onClick={onClickAdd} />
          <InCompleteTodos todos={inCompleteTodos} onCkickComplete={onCkickComplete} onCkickDelete={onCkickDelete} /> 
          <CompleteTodos todos={CompleteTodos} onClickBack={onClickBack} />
        </>
    );
};
```

### 11\.コンポーネントに該当するcssのスタイルもコンポーネントで分ける
今回はReactが用意しているインラインスタイルでコンポーネント化する。
また`InputoTodo`コンポーネント以外のコンポーネントは`class`を使いまわしている部分があるので、今回は`InputoTodo`コンポーネントのスタイルのみ格納する。

各コンポーネントの`className`は削除し、インラインスタイルでスタイルを記述していく。
可読性を考慮し一度変数に挟む形でコンポーネントに格納していく。

判定式は`isMaximiIncompleteTodos`という変数にすべて格納することで、仕様変更があった場合でも簡単に変更できるようにしておく

``` InputTodo.jsx
const style = {
    backgroundColor: "#c6e5d9",
    width: "400px",
    height: "30px",
    padding: "8px",
    margin: "8px",
    borderRadius: "8px",
}

export const InputTodo = (props) => {
    const {todoText, onChange, onClick} = props;
    return (
        <div className="input-area">
            <input placeholder="TODOを入力" value={todoText} onChange={onChange} />　//元はonChangeTodoText
            <button onClick={onClick}>追加</button> //元はonClickAdd
        </div>
    )
}
```

### 12\.Todoの上限設定
`InputoTodo`と`InCompleteTodos`の間にテキストを表示する<p>タグを用意。
そして`incompleteTodos`の配列の長さが5個以上の時だけ表示させたいので、`{}`の中に論理演算子で判定処理を記述。

```Todo.jsx
import { useState } from "react";
import { InputTodo } from "./components/InputTodo";
import { IncompleteTodos } from "./components/IncompleteTodos";
import "./styles.css";
import { CompleteTodos } from "./components/CompleteTodos";

export const Todo = () => {
  const [todoText, setTodoText] = useState("");
  const [incompleteTodos, setIncompleteTodos] = useState([]);
  const [completeTodos, setCompleteTodos] = useState([]);

  const onChangeTodoText = (event) => setTodoText(event.target.value);

  const onClickAdd = () => {
    if (todoText === "") return;
    const newTodos = [...incompleteTodos, todoText];
    setIncompleteTodos(newTodos);
    setTodoText("");
  };

  const onClickDelete = (index) => {
    const newTodos = [...incompleteTodos];
    newTodos.splice(index, 1);
    setIncompleteTodos(newTodos);
  };

  const onClickComplete = (index) => {
    const targetTodo = incompleteTodos[index]; // spliceする前に取得
    const newIncompleteTodos = [...incompleteTodos];
    newIncompleteTodos.splice(index, 1);

    const newCompleteTodos = [...completeTodos, targetTodo]; // ここでtargetTodoを使う
    setIncompleteTodos(newIncompleteTodos);
    setCompleteTodos(newCompleteTodos);
  };

  const onClickBack = (index) => {
    const newCompleteTodos = [...completeTodos];
    newCompleteTodos.splice(index, 1);

    const newIncompleteTodos = [...incompleteTodos, completeTodos[index]];
    setCompleteTodos(newCompleteTodos);
    setIncompleteTodos(newIncompleteTodos);
  };

  const isMaximiIncompleteTodos = incompleteTodos.length >= 5;

  return (
    <>
      <InputTodo
        todoText={todoText}
        onChange={onChangeTodoText}
        onClick={onClickAdd}
        disabled={isMaximiIncompleteTodos}
      />
      {isMaximiIncompleteTodos && (
        <p style={{ color: "red" }}>
          上限に達しました。タスクを消化してください。
        </p>
      )}
      <IncompleteTodos
        todos={incompleteTodos}
        onClickComplete={onClickComplete}
        onClickDelete={onClickDelete}
      />
      <CompleteTodos todos={completeTodos} onClickBack={onClickBack} />
    </>
  );
};

```
そして`InputTodo`コンポーネントの`input`と`button`に`disabled`という記述を追加することで、条件に達したときに機能できないようにする。
```InputTodo.jsx
const style = {
  backgroundColor: "#c6e5d9",
  width: "400px",
  height: "30px",
  padding: "8px",
  margin: "8px",
  borderRadius: "8px",
};

export const InputTodo = (props) => {
  const { todoText, onChange, onClick, disabled } = props;
  return (
    <div style={style}>
      <input
        disabled={disabled}
        placeholder="TODOを入力"
        value={todoText}
        onChange={onChange}
      />
      <button disabled={disabled} onClick={onClick}>
        追加
      </button>
    </div>
  );
};
```

以上でReactを使ったTODOアプリの制作が完了。