[React][L3] テキストボックスの内容を出力する

# 実施条件
[[React][L2] テキストボックスの内容を保持する](https://qiita.com/Jochun/items/38421fc6d54bc53a1820)を理解していること

# 環境
MacBook Pro (2.3 GHz 8コアIntel Core i9)
macOS 14.0（23A344）
Homebrew 4.3.8
gh 2.52.0

# ソースコードの前に
## フォルダ構成
~~~:folda_structure
├── package.json
├── public/
│   └── index.html
├── src/
│   ├── index.jsx
│   ├── Todo.jsx
│   └── styles.css
│　　
~~~

## index.html
~~~diff_html:index.html
<!DOCTYPE html>
<html lang="en">
  <head> </head>

  <body>
    <div id="root"></div>
  </body>
</html>
~~~

## index.jsx
~~~diff_jsx:index.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import { Todo } from "./Todo";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <Todo />
  </StrictMode>
);
~~~

# ソースコード
## Todo.jsx(旧)
~~~diff_jsx:Todo.jsx
import { useState } from "react";
import "./styles.css";

export const Todo = () => {

  const [todoText, setTodoText] = useState("");
  const [incompleteTodos, setIncompleteTodos] = useState([
    "TODOです1",
    "TODOです2",
  ]);
  const [completeTodos, setCompleteTodos] = useState([
    "TODOでした1",
    "TODOでした2",
  ]);

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

  return (
    <>
      <div className="input-area">
        <input placeholder="TODOを入力"></input>
        <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText}></input>
        <button>追加</button>
      </div>
      <div className="incomplete-area">
        <p className="title">未完了のTODO</p>
        <ul>
          {incompleteTodos.map((todo) => {
            return (
              <li key={todo}>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>完了</button>
                  <button>削除</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
      <div className="complete-area">
        <p className="title">完了のTODO</p>
        <ul>
          {completeTodos.map((todo) => {
            return (
              <li>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>戻す</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </>
  );
};
~~~

## Todo.jsx
~~~diff_jsx:Todo.jsx
import { useState } from "react";
import "./styles.css";

export const Todo = () => {

  const [todoText, setTodoText] = useState("");
  const [incompleteTodos, setIncompleteTodos] = useState([
    "TODOです1",
    "TODOです2",
  ]);
  const [completeTodos, setCompleteTodos] = useState([
    "TODOでした1",
    "TODOでした2",
  ]);

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

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

  return (
    <>
      <div className="input-area">
        <input placeholder="TODOを入力"></input>
        <input placeholder="TODOを入力" value={todoText} onChange={onChangeTodoText}></input>
-       <button>追加</button>
+       <button onClick={onClickAdd}>追加</button>
      </div>
      <div className="incomplete-area">
        <p className="title">未完了のTODO</p>
        <ul>
          {incompleteTodos.map((todo) => {
            return (
              <li key={todo}>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>完了</button>
                  <button>削除</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
      <div className="complete-area">
        <p className="title">完了のTODO</p>
        <ul>
          {completeTodos.map((todo) => {
            return (
              <li>
                <div className="list-row">
                  <p>{todo}</p>
                  <button>戻す</button>
                </div>
              </li>
            );
          })}
        </ul>
      </div>
    </>
  );
};
~~~

# 解説
## 目的
- `button`タグ(追加)を押下した時に、最新の`todoText`を、配列`incompleteTodos`に追加する

## コーディング
1. `button`タグ(追加)を押下した際に発火する、`onClick`イベントを設定する
    ~~~diff_jsx:Todo.jsx
    -       <button>追加</button>
    +       <button onClick={onClickAdd}>追加</button>
    ~~~

1. `onClick`イベントで呼び出される関数を`onClickAdd`として設定する
    ~~~diff_jsx:Todo.jsx
    + const onClickAdd = () => {
    + };
    ~~~

1. `onClickAdd`にて、スプレッド構文を用いて、最新の`todoText`の値を、配列`incompleteTodos`に追加して、`newTodos`として定義する
    ~~~diff_jsx:Todo.jsx
      const onClickAdd = () => {
    +     const newTodos = [...incompleteTodos, todoText];
      };
    ~~~

1. `newTodos`を配列`incompleteTodos`の更新関数である`setIncompleteTodos`に引数として渡す
    = 配列`incompleteTodos`を更新する
    ~~~diff_jsx:Todo.jsx
      const onClickAdd = () => {
          const newTodos = [...incompleteTodos, todoText];
    +     setIncompleteTodos(newTodos);
      }; 
    ~~~

1. テキストボックスを""に戻す
    ~~~diff_jsx:Todo.jsx
      const onClickAdd = () => {
          const newTodos = [...incompleteTodos, todoText];
          setIncompleteTodos(newTodos);
    +     setTodoText("");
      };
    ~~~

1. 値を入力していなくても、空文字で追加ができてしまうため、`if`で条件分岐する
    ~~~diff_jsx:Todo.jsx
      const onClickAdd = () => {
    +   if (todoText === "") {
    +     return;
    +   } else {
          const newTodos = [...incompleteTodos, todoText];
          setIncompleteTodos(newTodos);
          setTodoText("");
    +   }
      };
    ~~~


## 処理
1. `button`タグ(追加)を押下した際に、`onClickAdd`が起動する
1. `todoText`に保持された値が、配列`incompleteTodos`に追加され、`newTodos`に格納される
1. `newTodos`を引数として、`setIncompleteTodos`で配列`incompleteTodos`を更新する
1. 配列`incompleteTodos`を`map`メソッドで、レンダリングされる


# イメージ
## Todo.jsx(旧)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/f5f47b5a-8b71-6ebe-b14f-274f6101c266.png)

## Todo.jsx
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/ebdd2ea0-8020-7779-4e0e-506b9db8c01a.png)

# 参考リンク
- [if...else](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/if...else)
- [要素をクリックで処理開始! JavaScriptのonclickでイベントを指定](https://www.sejuku.net/blog/26119)
- [モダンJavaScriptの基礎から始める挫折しないためのReact入門
](https://www.udemy.com/course/modern_javascipt_react_beginner)