【React】ToDoアプリを作ってみよう【前編】

# :star2: 追記
リニューアルしました！

- [React + Redux + TypeScript でモダンなwebアプリを作るチュートリアルを考えてみた①](https://qiita.com/mikan3rd/items/2576c2f993d9c28d744c)


#:star: 対象
* Reactの概念をなんとなく理解したので、実際に簡単なアプリを作ってみたい方
* Reactの日本語チュートリアルがなくなって困っている方

#:star: 関連
* [Reactの環境構築を最短で行う](http://qiita.com/mikan3rd/items/496a87fc8b76263d0a91)
* [【React】ToDoアプリを作ってみよう【前編】](http://qiita.com/mikan3rd/items/20152cdd63a708264a9e)←ここ
* [【React】ToDoアプリを作ってみよう【後編】](http://qiita.com/mikan3rd/items/0a1be8fa9f349735cf4a)
* [【React】ToDoアプリを発展させよう【非同期処理】](http://qiita.com/mikan3rd/items/41e4a94a50fa6676542a)

#:star: 目標
* Reactで画像のようなToDoアプリを作ります。
* 今回はTodoを表示させるところまで実装してみましょう。
* 見本：[GitHub](https://github.com/mikan3rd/todo-list.react.js)

![todo-app4.gif](https://qiita-image-store.s3.amazonaws.com/0/178077/e23e6b23-4ed7-1ee0-df6b-372c382463ec.gif)


#:star: 手順
##:pencil: 環境構築
###:pencil2: [Reactの環境構築を最短で行う](http://qiita.com/mikan3rd/items/496a87fc8b76263d0a91)
* `package.json`があるディレクトリ（アプリ名のディレクトリ）で`npm start`を実行することでアプリが起動します。この状態でファイルを編集&保存すると、瞬時に結果が反映されるため、非常に便利です。

###:pencil2: ディレクトリ構成（例）
````
.
├── node_modules
├── package-lock.json
├── package.json
├── public
│   ├── data1.json
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
    ├── App.js
    ├── App.test.js
    ├── Form.js
    ├── Todo.js
    ├── TodoList.js
    ├── css
    │   ├── App.css
    │   ├── form.css
    │   ├── index.css
    │   └── todo.css
    ├── index.js
    └── registerServiceWorker.js

# 一部省略
````
* CSSを書くのが面倒な方は[こちらに見本](https://github.com/mikan3rd/todo-list.react.js)があるので使ってください。

##:pencil: Todoを表示させよう
###:pencil2: index.js
````js:src/index.js
import './css/index.css'
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'

ReactDOM.render(<App />, document.getElementById('root'))
````
* `import 〇〇 from 'ファイル名など'`：別のファイルで指定した〇〇（クラス名や変数）を使うことができます。`import React from 'react'`はReactを使うファイルでは必須です。
* `ReactDOM.Render()`でHTMLのidのある場所にコンポーネントを挿入します。今回は、`public/index.html`
にある`<div id="root"></div>`にAppコンポーネントを挿入しています。

###:pencil2: App.js
````js:src/App.js
import React, { Component } from 'react';
import TodoList from './TodoList';
import './css/App.css'


class App extends Component {

  constructor() {
    super()
    this.state = {
      todos: [
        {
          id: 1,
          title: "Hello, React!",
          desc: "React始めました",
          done: false
        },
        {
          id: 2,
          title: "Hello, Redux!",
          desc: "Reduxも始めました",
          done: false
        },
      ]
    }
  }

  render() {
    return (
      <div className="app">
        <h1>todoアプリを作ってみた</h1>
        <TodoList
          todos={this.state.todos}
          />
      </div>
    );
  }
}

export default App


````
* `class 〇〇 extends Component{}`でコンポーネントと呼ばれるクラスを作成します。これを組み合わせて様々なviewを作れるのがReactの特徴の一つです。
* `constructor`では初期値を設定します。`super()`は`Component`を継承するため必須です。
* `this.state`はこのクラスのstateを示しています。今回はtodosという配列に各キーとバリューを設定しておきます。
* `render(){}`でHTMLとして渡したい変数などを設定し、`return()`の中に実際に返したいHTMLそのものを記述します。実際にHTMLに近いJSXと言う記法です。HTMLのclassはJSXではclassNameとなるので気をつけましょう。
* 呼び出したいコンポーネントは`<TodoList />`のように記述します。さらに、`todos={this.state.todos}`のように、そのコンポーネントに渡したい内容も書いてあげましょう。これで、TodoListでtodosという変数を使えるようになりました。
* `export default 〇〇`でimportされた時にデフォルトで呼び出されるものを定義します。

###:pencil2: TodoList.js
````js:src/TodoList.js
import React, { Component } from 'react';
import Todo from './Todo';


class TodoList extends Component {

  render() {
    const todos = this.props.todos.map( todo =>
      <Todo
        key={todo.id}
        {...todo}
      />
    )

    return(
      <ul>
        {todos}
      </ul>
    );
  }
}

export default TodoList
````
* 親コンポーネントから渡されたものは`this.props`を使って受け取ることができます。
* TodoListから複数のTodoができる時など、子コンポーネントに同じ形式の配列を渡す時は、それらを区別するための絶対に重複しない**key**を設定する必要があります。今回は`todo.id`をkeyに入れます。
* `{...todo}`はtodoに入っている要素を全て引き継ぐ、と言う意味です。
* returnで<Todo />の配列の入った**todos**を返すことで、Todoコンポーネントでpropsとして受け取ることができます。`{}`で変数展開ができます。

###:pencil2: Todo.js
````js:src/Todo.js
import React, { Component } from 'react';
import './css/todo.css';

class Todo extends Component {

  render() {
    const className = 'undone'
    const link = this.props.done ? '元に戻す' : '完了！'
    return(
      <li className={className}>
        <span>{this.props.id}</span>
        <span>：{this.props.title}　　</span>
        <a href="">{link}</a>
        <p>{this.props.desc}</p>
      </li>
    );
  }

}

export default Todo
````
* `const link`は三項演算子を使って定義しています。`this.props.done`がtrue（完了済）の時は「元に戻す」ボタン、false(未完了)の時は「完了」ボタンを表示するようにします。
* returnの中でHTMLとして表示したい用要素を組み立てて完成です。

<img width="660" alt="スクリーンショット 2017-07-14 14.24.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/178077/30359065-8f99-e624-b5c0-17b01b769dfd.png">
###:star2: 今回はここまで！
* 内容に不備等ありましたら、お手数ですがコメントにてお願いします。

#:star: 参考
* [一人React.js Advent Calendar](http://qiita.com/advent-calendar/2014/reactjs)
* [ES6版React.jsチュートリアル](http://qiita.com/nownabe/items/2d8b92d95186c3941de0)