【React】TODOアプリ作りながらReactの基礎(レンダリングの仕組み/状態管理)を学ぶ

## まえがき
百聞は一見に如かずということで、TODOアプリを作りながらReactを学んでいきます。

## 環境構築＆プロジェクト作成
基本的に↓に書いてある通り進めていく。

https://ja.reactjs.org/tutorial/tutorial.html#setup-for-the-tutorial

・NodeJSがインストールされていること `node -v`
・プロジェクト作成
```
# React × JavaScript
npx create-react-app react-practice

# React × TypeScript
npx create-react-app react-practice --template typescript
```

・動作確認
```
cd react-practice
npm start
```

初期画面が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653955/6a31ab4f-0f26-820e-7738-e6b240831054.png)

## プロジェクト構成
・src
　- Reactのソースコードをここに書いていく。
・public
　- HTMLファイル/画像ファイル等 ... HTTPリクエストで取得されるやつら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653955/3fb1476f-4149-7b0d-c449-ddeac7808e03.png)
## レンダリングの流れ
### index.htmlとindex.js
・index.htmlに対して、React(JavaScript)がレンダリングの処理をかける。
・`ReactDOM.render()`＝レンダリング
・`ReactDOM.render(①React要素, ②①を反映する場所)`
　①React要素 を ②index.htmlの`<div id="root"></div>`に反映する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653955/1507e781-d711-02e9-a95c-c6208ce87c71.png)
### App.js
・index.jsでは`import App from './App';`で参照している`App.js`を元にレンダリングしているので、このApp.jsとそれに繋げるコンポーネントを作成していくことでReactアプリケーションを実装していく流れとなる。

・exportされているApp関数は、**HTMLっぽいやつ**を戻り値に返す関数。
・index.jsの``ReactDOM.render()``の第１引数には**React要素**を渡す必要があるので、この**HTMLっぽいやつを書けばReact要素が生成される**。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653955/04026f35-dd7a-3c0f-bc80-a1e009e5359a.png)
### HTMLっぽいやつの正体 = 「JSX」というプログラミング言語
・HTMLっぽいやつは「**JSX**」というプログラミング言語である。
・JSXで書かれた処理は**React.createElement関数でReact要素を生成する処理**に変換される。
　↓なぜ？↓
・**ReactDOM.render()の第１引数に渡すReact要素を生成する処理が、まさにこのReact.createElement関数だから。**
・毎回↓のような書き方をしてReact要素を定義するよりも、JSXのような**HTMLっぽいやつ**の方が当然書きやすいからJSXを使うよね～という感じ。

```js
// aは"React要素"
var a = React.createElement('h1', { myaddr: 'bar' }, 'First element!')
// 第１引数にReact要素が渡される
ReactDOM.render(a, document.getElementById('root'))
```

### React.createElement関数の戻り値
・React.createElement returns **an object** that represents the DOM element.
```tsx
const element = React.createElement("h1");
//returns an object similar to this one:
{
  type: 'h1',
  props: {}
}
```

https://react-tutorial.app/app.html?id=338

## TODOアプリ作っていく。

### 入力して追加する

参考

https://zenn.dev/sprout2000/articles/60cc8f1aa08b4b

TODOアプリ作るうえで必要な機能
・「追加」を押したら、TODOタスク一覧に反映されること
・反映されたTODOタスクは残り続けること
・「実行済」にしたらタスクが消えること
つまり「**状態**」を保持する必要がある。Reactでは**React Hooks**を使って状態管理を実現する。

先ほどの`App.js`に直接書いてみた。
```js
import { useState } from 'react';

function App() {

 /**
  * todo = ステートの値
  * setTodo = ステートの値を更新するメソッド
 */
  const [todo, setTodo] = useState(``)
  const [todoList, setTodoList] = useState([]);
  
  // TODOリストに入力項目を追加する関数
  const addTodoList = () => {
    if (!todo) return
    const newTodoList = [todo];
    // 配列(オブジェクト)に対して"イミュータブル"な操作で追加する
    setTodoList([newTodoList, ...todoList]);
    setTodo(``);
  }

  return (
    <div>
      <h1>TODOタスク一覧</h1>
      <ul>
        {todoList.map((item) => {
          return <li>{item}</li>
        })}
      </ul>
      <form onSubmit={(e) => {
        e.preventDefault();
        addTodoList();
      }}>
          
        <input
          type="text"
          value={todo}
          onChange={(e) => setTodo(e.target.value)}
        />
        <input
          type="submit"
          value="追加"
          // addTodoList関数そのもの渡す。
          // 実行自体はform要素のonSubmit()で実施する
          onSubmit={addTodoList}
        />
      </form>
    </div>
  );
}

export default App;
```
こんな感じになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653955/ad255f2b-605c-1541-8bce-dbdf5ef669ed.png)

### 追加したものを「実行済」にして消す　※後日追記