React TODOアプリ作成


こちらの記事は以下の書籍を参考にアウトプットとして執筆しました
[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

#TODOアプリに必要なコンポーネント

|コンポーネント|説明|
|---|---|
|App|各コンポーネントのまとめ役。データ管理|
|TodoInput|入力フォームと登録ボタン|
|TdoItem|1つのTodo。タイトルと削除ボタンをもつ|
|TodoList|Todoの一覧|


##Appコンポーネント
```javascript
import React,{Component} from 'react'
```

これはどういう意味なのだろうか。
`import X from Y`ならわかるが`{}`が出てきて`,`で区切られている

```javascript
//デフォルトエクスポートはReactという名前で、
//また、Componentという名前付きエクスポートをインポートしている
import React,{Component} from 'react'
```
デフォルトエクスポートは1つのモジュールに1つ定義でき、
名前付きエクスポートは1つ以上定義できる。

```javascript
import React,{Component} from 'react';
import TodoInput from './TodoInput';
import TodoList from './TodoList';

class App extends Component{
  render(){
    //TODO：後々stateで管理する
    const tasks=[
      {title:'Todo1つ目',id:0},
      {title:'Todo2つ目',id:1},
    ];
    return (
      <div>
        <h1>TODO App</h1>
        <TodoInput/>
        <TodoList tasks={tasks}/>
      </div>
    )
  }
}
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

このコードは`'react'`からデフォルトエクスポートのReactと名前付きエクスポートのComponentをインポートし、

Componentを継承したAppクラスを定義している。

Appクラスの中身を見てみると
renderメソッド一つだけを定義している。
このメソッドはJSXを返す。

##TodoInputコンポーネント
App.jsを見てみるとTodoinputコンポーネントのjsファイルはApp.jsと同じディレクトリに作成するようだ

```javascript
import React, { Component } from 'react';

class TodoInput extends Component {
    render() {
        return (
            <div>
                <input placeholder="新規TODOを入力" />
                <button>登録</button>
            </div>
        )
    }
}

export default TodoInput;
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

ここではTodoInputクラスを定義していて
renderメソッドを持っている

後はTodoInputをデフォルトエクスポートしている

##TodoList
```javascript
import React, { Component } from 'react';
import TodoItem from './TodoItem'

class TodoList extends Component {
    render() {
        //tasks内の各todoをTodoItemコンポーネントでエレメントにしている
        //list変数はTodoItemエレメントの配列が入っている
        const list = this.props.tasks.map(todo => {
            return <TodoItem {...todo} key={todo.id} />
        })
        return (
            <div>
                <ul>
                    {list}
                </ul>
            </div>
        )
    }
}

export default TodoList;
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

```javascript
        const list = this.props.tasks.map(todo => {
            return <TodoItem {...todo} key={todo.id} />
        })
```
App.jsでReactコンポーネントを

```javascript
<TodoList tasks={tasks}/>
```
と定義してい箇所があるため、TodoList.jsでの
`this.props.tasks`には

```javascript
const tasks=[
      {title:'Todo1つ目',id:0},
      {title:'Todo2つ目',id:1},
    ];
```
が入る。

そしてこれを`map`で処理して新しいlist配列を生成している。
よって`<TodoItem {...todo} key={todo.id} />`が展開されると以下のようになる

```javascript
<TodoItem title='Todo1つ目' id=0 key=0 />
<TodoItem title='Todo2つ目' id=0 key=1 />
```

そしてTodoInHtemが入ったlist配列をrenderメソッドが返している。

##TodoItem
```javascript
import React from 'react'

function TodoItem(props) {
    return (
        <li>
            {props.title}
        </li>
    )
}
export default TodoItem;
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

##state初期値
Appのtasksをstateで管理する。
初期値はconstructorで設定する

```javascript:App.js
import React, { Component } from 'react';
import TodoInput from './TodoInput';
import TodoList from './TodoList';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      tasks: [
        {
          title: 'デフォルトTODO',
          id: 0,
        },
      ],
      uniqueId: 1,
    }
  }
  render() {
    return (
      <div>
        <h1>TODO App</h1>
        <TodoInput />
        <TodoList tasks={this.state.tasks} />
      </div>
    )
  }
}
```
stateは定義するためにconstructorで設定
以降変更するときはsetStateを使う
superでComponent側のconstructorでpropsを処理

###addTodoメソッドの追加
新規TODOを追加できるようのメソッドを作成

```javascript:App.js
  addTodo(title) {
    const { tasks, uniqueId, } = this.state;
    tasks.push({
      title, id: uniqueId
    })
    this.setState({
      tasks, uniqueId: uniqueId + 1
    })
  }
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

```javascript
//これは分割をしている。
const { tasks, uniqueId, } = this.state;

//これは以下と同義
const tasks = this.state.tasks
const uniqueId = this.state.uniqueId
```

```javascript
tasks.push({
      title, id: uniqueId
    })
```
これは省略されている。
`title`はプロパティ名を`title`として値を変数titleの値を設定している。

後はsetStateでstateに保存している。

このaddTodoをTodoInputで使うために渡す

```javascript
<TodoInput addTodo={this.addTodo} />
```

最後にaddTodoメソッドで適切にstateを変更するために以下のコードを追記

```javascript:App.js
constructor(props) {
   //中略
   this.addTodo=this.addTodo.bind(this)
  }
```
bindはすべてのfunctionオブジェクトが持っているメソッド

addTodoメソッドでのthisはAppコンポーネントのつもりで書いているが、実際このメソッドを実行するのは別のDOM、コンポーネントであるため、stateを持たないものもある。

これを書くことでaddTodoのなかの**this**は常にAppインスタンスを指し、**this.state**はAppコンポーネントのstateを参照する。

bindを使わない方法として、アロー演算子を使うなどの手法があるが、コンポーネントを渡すときに毎回アロー関数を書く必要があるなど、手間が増えるため、当面はbindを使っていったほうがいい

##イベントハンドリング
TodoInputにはpropsとしてaddTodoが渡されていた

```javascript
<TodoInput addTodo={this.addTodo} />
```
クリックするたびにaddTodoメソッドを呼ぶメソッドを新たに追加

```javascript
import React, { Component } from 'react';

class TodoInput extends Component {
    constructor() {
        super(props)
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick() {
        this.props.addTodo('新規TODO')
    }
    render() {
        return (
            <div>
                <input placeholder="新規TODOを入力" />
                <button onClic={this.handleClick}>登録</button>
            </div>
        )
    }
}

export default TodoInput;
```
参考：[React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで](https://www.amazon.co.jp/React%E5%85%A5%E9%96%80-React%E3%83%BBRedux%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%82%88%E3%82%8BUX%E3%81%AE%E5%90%91%E4%B8%8A%E3%81%BE%E3%81%A7-%E7%A9%B4%E4%BA%95%E5%AE%8F%E5%B9%B8-ebook/dp/B078XDLL2J/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=)

またコンストラクタでbindしてhandleClickメソッドでのthisは常にTodoInputコンポーネントを指すことになった

button要素にonClick属性で関数を渡している。
これはブラウザのイベントと同じような感覚で引数も扱える。
##from操作
Reactはフォーム入力もstateとして扱う。
フォーム入力はこのコンポーネントのみで利用するので(このコンポーネントってどこだよって読んでて思った)親コンポーネントのAppで定義する必要はない

次にstateとして持っている値をinput要素のvalueに設定
最後にユーザの入力ごとに実行され、その都度入力されている値をstateにセットするメソッドを書く