【初心者向け】Reactで動くToDoアプリの作り方

## ご挨拶

[Ateam Lifestyle Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam-lifestyle)の8日目は、株式会社エイチームライフスタイル デザイナー @snd-07 が担当します！

## この記事について

2020年を振り返ってみると、業務触れるReactを理解するため、フロントエンドの勉強が中心でした。
Progateやドットインストールなどで学習を進め、「なんとなく書いてあることはわかる」「こういう機能がある」という所まではステップアップできたと思います。

しかし現在、実践でコードを書くことができない所が課題になっているので、実際に簡単なアプリを作ることにしました。
また、Qiitaに投稿することで、自分の理解を言語化するチャレンジにしようと考えています。

できるだけ、自分がどう考え、どうしたかを記載し、私のようなフロントエンドの勉強を始めたばかりの人でもトライしやすいような記事にしていますので、ぜひみなさんも見ながらチャレンジしてみてください。
「Reactを勉強しはじめたばかり」「何か作ってみたいけど、何から始めたらいいか分からない」といった人におすすめです:sun_with_face:

## 作ったもの
### 機能

- タスク一覧を表示する
- タスクを追加できる
- タスクを削除できる

### 挙動
![todoアプリ挙動.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250206/1953bd4d-1b48-96b0-a286-060854827da2.gif)

## 作成手順

### 1. UIを作る

- まずはUIを作ります。
    - 最初からコンポーネントにしてしまったり、jsを書いてしまうと頭が混乱してしまいます:frowning2:
    - 仮の文字などで、ベタで書いて１つずつ進めていくことにします。

```App.jsx
import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <h1 className="title">TODO</h1>
      <ul className="list">
        <li>
          タスク1
          <button className="delete">×削除</button>
        </li>
        <li>
          タスク2
          <button className="delete">×削除</button>
        </li>
      </ul>
      <div className="add">
        <input
          name="title"
          type="text"
          className="addInput"
          placeholder="タスクを追加する"
        />
        <button className="addButton">追加する</button>
      </div>
    </div>
  );
}
```

- まだボタンを押しても何の処理も走りません。タスクのリストも、仮のテキストで作っておきます。
- style.cssはここでは省略します。（[こちらで見ることができます](https://codesandbox.io/s/todoapuri-mklm2?file=/src/styles.css)）

### 2. タスクを配列で管理し、追加できるようにする

- 「タスクを追加する」ボタンを押すと、`<li></li>`に追加されるようにします。

#### 2.1 タスクを配列にして表示させる

```App.jsx
const tasks = ["タスク1", "タスク2"];
```
```App.jsx
<ul className="list">
  {tasks.map((task) => {
    return (
      <li key={task}>
        {task}
        <button className="delete">×削除</button>
      </li>
     );
  })}
</ul>
```
- 一旦、配列で表示できるところまででチェック◎
- ポイント
    - 配列の要素で新たな配列を作るために`map`を使用 - [Array.prototype.map() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
    - Reactはそれぞれの項目にkeyを与えなければならないので`key`を与える - [リストと key – React](https://ja.reactjs.org/docs/lists-and-keys.html)

#### 2.2 追加ボタンを押したら配列に追加されるようにする

```App.jsx

const [tasks, setTasks] = useState(["タスク１", "タスク2"]); //const tasks = ["タスク1", "タスク2"]; は削除
const [text, setText] = useState("");
```

```App.jsx
<div className="add">
  <input
    name="title"
    type="text"
    className="addInput"
    placeholder="タスクを追加する"
    value={text}
    onChange={(event) => {
      setText(event.target.value);
    }}
  />
  <button
    className="addButton"
    onClick={() => {
      setTasks((task) => task.concat(text));
      setText("");
    }}
  >
    追加する
  </button>
</div>
```

- ポイント
    - 状態を管理する`useState`を使用 - [ステートフックの利用法 – React](https://ja.reactjs.org/docs/hooks-state.html)
    - valueに入れたテキストを配列に追加するために`concat`を使用 - [JavaScriptの配列の使い方まとめ。要素の追加,結合,取得,削除。 - Qiita](https://qiita.com/takeharu/items/d75f96f81ff83680013f)

### 3. タスクを削除ボタンで削除できるようにする

- 削除ボタンを押すと、配列からその要素を削除できるようにします。

```App.jsx
const handleRemoveTask = (index) => {
    const newTasks = [...tasks];
    newTasks.splice(index, 1);
    setTasks(newTasks);
  };
```
```App.jsx
<ul className="list">
  {tasks.map((task,index) => {
    return (
      <li key={task}>
        {task}
        <button
          className="delete"
          onClick={() => {
            handleRemoveTask(index);
          }}
        >
          ×削除
        </button>
      </li>
     );
  })}
</ul>
```

- ポイント
    - 要素を削除し、配列を組み替えるために`splice`を使用 - [.splice() | JavaScript 日本語リファレンス | js STUDIO](http://js.studio-kingdom.com/javascript/array/splice)

### 4. 完成！

```App.jsx
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [tasks, setTasks] = useState(["タスク１", "タスク2"]);
  const [text, setText] = useState("");
  const handleRemoveTask = (index) => {
    const newTasks = [...tasks];
    newTasks.splice(index, 1);
    setTasks(newTasks);
  };
  return (
    <div className="App">
      <h1 className="title">TODO</h1>
      <ul className="list">
        {tasks.map((task, index) => {
          return (
            <li key={index}>
              {task}
              <button
                className="delete"
                onClick={() => {
                  handleRemoveTask(index);
                }}
              >
                ×削除
              </button>
            </li>
          );
        })}
      </ul>
      <div className="add">
        <input
          name="title"
          type="text"
          className="addInput"
          placeholder="タスクを追加する"
          value={text}
          onChange={(event) => {
            setText(event.target.value);
          }}
        />
        <button
          className="addButton"
          onClick={() => {
            setTasks((task) => task.concat(text));
            setText("");
          }}
        >
          追加する
        </button>
      </div>
    </div>
  );
}

```

## まとめ

いかがだったでしょうか？

実際に作ってみたいものを作ってみることで、ただ文法をインプットするより、ぐんと理解度・書く力が上がりました。
次は、もっと複雑なものにチャレンジしてみようと思います！
また、この記事を書く上で、自分の実装・思考を振り返って整理することができたので、Qiitaへのアウトプットも継続して行いたいです。
これからも引き続き学習を進めていきます:tulip: