【React Native】アプリ開発未経験のフロントエンドエンジニアがToDoリストを作ってみる

# はじめに
普段はAngularなどでWebアプリケーションを開発している私ですが、急に[React Native](https://facebook.github.io/react-native/)を学びたくなったので、徒然とこの記事を書きはじめました。
↓な感じのToDoリストを作ります。

<img width="300" alt="ToDo" src="https://qiita-image-store.s3.amazonaws.com/0/13947/169370f2-8b64-e5ae-2b1e-3f1971394072.png">

最終成果物はこちらです。
[todo-sample](https://github.com/daiend/todo-sample)

# この記事でわかること
- **React Nativeの基礎の基礎**

ベストプラクティス的なやつとか、こんな応用的な使い方してやったぜ！みたいなのは全く書いてません。

# まずはインストールしないとはじまらない
React Nativeには「[node](https://nodejs.org/ja/)」と「[watchman](https://facebook.github.io/watchman/)」が必要らしいので、さくっとインストールします。

```
brew install node
brew install watchman
```

続いて、React Nativeの本体をインストールです。

```
npm install -g react-native-cli
```

# プロジェクトを作って起動してみる
```
react-native init Todo
cd Todo
react-native run-ios
```

<img width="300" alt="Welcome" src="https://qiita-image-store.s3.amazonaws.com/0/13947/4b166908-96ed-f245-1f08-2e50d3d0d56b.png">

この画面が表示されれば起動成功です。
ちなみにシミュレーター上で「**Command + D → Debug JS Remotely**」を選択することで、デベロッパーツールによるデバッグできるので、覚えておいたほうが良いです。

# 簡単に設計する
この後は「index.ios.js」に処理をズンズン書いていけば何とかなりそうですが、せっかくなので手を動かす前に必要なClassはどんな感じになるか考えてみます。

<img width="300" alt="スクリーンショット_2016-12-18_18_20_40_.png" src="https://qiita-image-store.s3.amazonaws.com/0/13947/4318636e-9cf7-8539-a9f4-553861186ce2.png">

- TodoListContainer  
画面を囲うContainer。TodoListとFooterを持つ。
- TodoList  
TodoList全体。TodoListItemを持つ。
- TodoListItem  
TodoList単体。CheckboxとTodoを表示するTextを持つ。
- Footer  
画面下部に固定されているFooter。textInputと追加ボタンを持つ。

最低これらのClassがあれば何とかなりそうです。

# 初期データを表示する
まずは「index.ios.js」をいじくって、TodoListContainerを初期化します。

- index.ios.js

```Javascript
import React, { Component } from 'react';
import {
  AppRegistry
} from 'react-native';

import TodoListContainer from 'Todo/src/TodoListContainer';

class Todo extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <TodoListContainer />
    );
  }
}

AppRegistry.registerComponent('Todo', () => Todo);
```

データは、Todoを追加する処理をする「Footer」とTodoを描画する「TodoList」の橋渡し的な役割を担う「TodoListConainer」に持たせます。

 - TodoListContainer.js
 
```Javascript
this.state = {
  todos: [
    {text: 'Learn react native'},
    {text: 'Make a to-do app'}
  ]
}
```

そして、「TodoList」のpropsにデータを渡します。
stateとpropsは下記が参考になります。
[React における State と Props の違い](http://qiita.com/kyrieleison/items/78b3295ff3f37969ab50)

```Javascript
render() {
  return (
    <View style={{flex: 1}}>
      <ScrollView
        style={styles.base}
      >
        <TodoList
          todos={this.state.todos} //TodoListのpropsにデータを渡す
        />
      </ScrollView>
     ・・・
}
```

続いて、ReactNativeで用意されているコンポーネントである「ListView」でTodoを描画します。

 - TodoList.js

```Javascript
constructor(props) {
  super(props);

  //ListViewで扱うデータ形式にする
  this.dataSource = new ListView.DataSource({
    rowHasChanged: (row1, row2) => row1 !== row2
  });
}

render() {
  return (
    <ListView
      dataSource={this.dataSource.cloneWithRows(this.props.todos)}
      renderRow={(todo) => <TodoListItem {...todo} />}
      renderSeparator={this.renderSeparator}
    />
  );
}
```

 - TodoListItem.js

```Javascript
render() {
  return (
    <View style={styles.todo}>
      <CheckBox
        isChecked={this.props.complete}
        onClick={()=>this.onClick()}
      />
      <Text style={[styles.text, this.state.isChecked ? styles.isTextDisabled : null]}>
        {this.props.text}
      </Text>
    </View>
  );
}
```

Checkboxは下記コンポーネントを使わせていただきました。
[react-native-check-box](https://github.com/crazycodeboy/react-native-check-box)

# Todoを追加する
Todoの追加は「Footer」に配置してある「追加」が押されたタイミングで、「TodoListContainer」のstateを更新して行います。

- Footer.js

```Javascript
onAddPress() {
  // TodoListContainerのaddTodoメソッドにtextを渡して実行
  this.props.addTodo(this.state.text);

  // Todo追加後はTextInputを空にする
  this.setState({
    text: ''
  });
}
```

- TodoListContainer.js

stateにセットした配列に新しく値を追加する際は、concatで処理するのが定石っぽいのでそうします。

```Javascript
addTodo(text) {
  this.setState({
    todos: this.state.todos.concat([{text: text}])
  });
}
```

<img width="300" alt="スクリーンショット 2016-12-18 22.36.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/13947/17a7058c-2d95-7b61-71f9-df0581a57778.png">

追加された！∩( ・ω・)∩ばんじゃーい

# おわりに
そんなこんなでToDoリスト(ToDoの削除ができないのは気にしない)が出来上がりました。
React.jsをある程度知っていれば思った以上に高速で開発できますね…
やっててよかったReact.js。