今からはじめるReact.js〜サーバーとの通信〜

前回→[今からはじめるReact.js〜仮想環境を作成する〜](http://qiita.com/kuniken/items/bc01ece78784f36a9906)

# React.jsからサーバー通信
## SuperAgant
React.jsでAjax通信する場合、jQueryを利用するか、その他の手段を使うか検討すると思いますが、Ajax通信するためだけにjQueryを使うのは無駄が多いので、SuperAgantを利用することにします。

SuperAgantの使い方については、
http://qiita.com/hashrock/items/3113690bb3de5bba639b
の解説がわかりやすかったです。
インストールは次の通りです。
`$ npm install superagent --save`

## テーブルを作成する
今回、ユーザーを登録できるのと、ユーザーリストを表示できるように実装します。
サーバー通信の実装を行う前に、ユーザーテーブルを作成します。
カラムはnameとmailだけの単純なものです。

### pgAdminのインストール
自端末側でデータベースを見ながら作業したいので、ツールをインストールします。
pgAdminを使用することとします。
Mac->http://www.pgadmin.org/download/macosx.php
Win->http://www.pgadmin.org/download/windows.php
から圧縮ファイルをダウンロードしてインストールします。

インストールしたら、起動してサーバーの追加を行います。
![スクリーンショット 2015-10-16 16.35.52.png](https://qiita-image-store.s3.amazonaws.com/0/89819/299a127a-1f2c-5497-4919-81add73c9dc9.png)
パスワードはpostgreSQLをインストールした際にpostgresユーザーに付与したパスワードのことです。

OKをクリックしたらサーバーが追加されます。
（Saving passwordsの画面が出たらOKをクリック）
![スクリーンショット 2015-10-16 16.38.49.png](https://qiita-image-store.s3.amazonaws.com/0/89819/e39d53b3-bac5-d72a-f950-f3d220827196.png)

### usersテーブルを作成
postgresデータベースのpublicスキーマにusersテーブルを作成します。
「テーブル」ディレクトリを右クリックして、「新しいテーブル」をクリックします。
![スクリーンショット 2015-10-16 16.40.46.png](https://qiita-image-store.s3.amazonaws.com/0/89819/9a3bdb23-b6e3-856c-3cda-6dc1c07c7fde.png)

テーブル定義は以下の通りです。
![スクリーンショット 2015-10-16 16.42.07.png](https://qiita-image-store.s3.amazonaws.com/0/89819/b118f6d3-0085-69f2-87e6-b91b4c7bf785.png)

「列」をクリックして、カラムの追加を行います。
![スクリーンショット 2015-10-16 16.43.37.png](https://qiita-image-store.s3.amazonaws.com/0/89819/83280740-4200-d446-7eec-0111b911a826.png)

追加ボタンをクリックします。
プライマリーキーとなるidを追加します。データ型はserialとしておきます。
![スクリーンショット 2015-10-16 16.45.30.png](https://qiita-image-store.s3.amazonaws.com/0/89819/6aa4c189-e711-ea19-c77b-139ce401d02e.png)

nameとmailについても以下のように追加します。
name
![スクリーンショット 2015-10-16 16.47.17.png](https://qiita-image-store.s3.amazonaws.com/0/89819/0f5e2699-8502-cf46-4029-9694a3cf9bad.png)

mail
![スクリーンショット 2015-10-16 16.48.19.png](https://qiita-image-store.s3.amazonaws.com/0/89819/6f0ca47d-4e85-0465-2152-09b21e3874e4.png)

こんな感じになります。
![スクリーンショット 2015-10-16 16.48.51.png](https://qiita-image-store.s3.amazonaws.com/0/89819/9bf53051-9686-5384-90ea-2444c069132f.png)

最後に、プライマリーキーを指定します。

「制約」で追加ボタンをクリックします。
![スクリーンショット 2015-10-16 16.49.43.png](https://qiita-image-store.s3.amazonaws.com/0/89819/bd50c312-bf74-20f4-6161-8dae2729cd02.png)

プロパティは、以下のようにします。
![スクリーンショット 2015-10-16 16.50.59.png](https://qiita-image-store.s3.amazonaws.com/0/89819/75a7f280-aecf-fd0e-b792-00f00326bd68.png)

列でidを指定して追加ボタンをクリックします。
![スクリーンショット 2015-10-16 16.52.15.png](https://qiita-image-store.s3.amazonaws.com/0/89819/c9d8999e-a0f0-3454-a803-f71905a62a99.png)

OKボタンをクリックすると、以下のように表示されるはずです。
![スクリーンショット 2015-10-16 16.53.05.png](https://qiita-image-store.s3.amazonaws.com/0/89819/87c92e23-f68c-676f-0553-2ddff243ac08.png)

OKをクリックして設定を確定します。
下記のようにテーブルが作成されているはずです。
![スクリーンショット 2015-10-16 16.55.08.png](https://qiita-image-store.s3.amazonaws.com/0/89819/d3562e06-0611-d25b-821b-f7ddb29cef23.png)

## React.jsの実装
テーブルが作成できたら、ソースを書きましょう。body.jsxを編集します。

UserBoxコンポーネントの中にAjaxの処理を追記します。
今回実装したい処理としては、
・画面表示時にusersテーブルからデータを取得してリストに表示する
・追加ボタンをクリックした際にusersテーブルに入力データを追加してリストを最新データで再表示する
になります。

画面が表示された際になんらかのイベントを行いたい場合はcomponentDidMountメソッドを記述します。
更新するイベントは既存のhandleAddUserを編集するだけでいけそうですね。

```js:body.jsx
//フォームとリストを一つにしたもの
var UserBox = React.createClass({
  getInitialState:function(){
    return {userData:[]};
  },
  handleAddUser:function(name, mail){
    //ユーザーをDBに登録する
    //ユーザー一覧を取得する（結果をthis.state.userDataにセット）

    //var data = this.state.userData;
    //data.push({name: name, mail: mail});
    //this.setState({userData: data});
  },
  componentDidMount:function(){
    //ユーザー一覧を取得する（結果をthis.state.userDataにセット）
  },
  render:function(){
    return(
      <div style={{width:"300px"}}>
        <UserForm addUser={this.handleAddUser}/>
        <hr/>
        <UserList userData={this.state.userData}/>
      </div>
    );
  }
});
```
やることが決まったらプログラムを書きます。
### ユーザーをDBに登録するイベントの作成

postメソッドを実行するように書きます。

```js:body.jsx
var React = require('react');
var ReactDOM = require('react-dom');
var request = require('superagent');
  :
  :
  :
  handleAddUser:function(name, mail) {
    var url = "/post_user";
    //ajax通信する
    request
      .post(url)
      .send({name: name, mail: mail})
      .end(function(err, res){
        if (err) {
          alert(res.text);
        }
        var map = JSON.parse(res.text);
        //表示されている値を更新
        this.setState({userData: map});
      }.bind(this));
  }
```
まずはsuperagentをインポートします。
次に、
postメソッドを使ってサーバー通信します。
urlは `http://192.168.33.10:5000/post_user` 。
postしたいデータをsendで設定。
postの結果はendで処理します。

通信が成功した場合、サーバー側からはユーザー一覧を返してもらいます。
返されるデータはテキストで返されますので、処理しやすいようにJSONオブジェクトに変換します。

最後にsetStateします。これでリストの表示が更新されます。

### ユーザー一覧を取得するイベントの作成
getメソッドを定義します。

```js:body.jsx
  getUsers:function(name, mail) {
    var url = "/get_users";
    //ajax通信する
    request
      .get(url)
      .query({})
      .end(function(err, res){
        if (err) {
          alert(res.text);
        }
        var map = JSON.parse(res.text);
        //表示されている値を更新
        this.setState({userData: map});
      }.bind(this));
  }
```
urlは http://192.168.33.10:5000/get_user 。
getする際の条件があればqueryで設定（今回は無し）。queryは省略しても実行できます。

以上をまとめると、以下のようになります。

```js
//フォームとリストを一つにしたもの
var UserBox = React.createClass({
  getInitialState:function(){
    return {userData:[]};
  },
  getUsers:function(name, mail) {
    var url = "/get_users";
    //ajax通信する
    request
      .get(url)
      .query({})
      .end(function(err, res){
        if (err) {
          alert(res.text);
        }
        var map = JSON.parse(res.text);
        //表示されている値を更新
        this.setState({userData: map});
      }.bind(this));
  },
  handleAddUser:function(name, mail){
    var url = "/post_user";
    //ajax通信する
    request
      .post(url)
      .send({name: name, mail: mail})
      .end(function(err, res){
        if (err) {
          alert(res.text);
        }
        var map = JSON.parse(res.text);
        //表示されている値を更新
        this.setState({userData: map});
      }.bind(this));
  },
  componentDidMount:function(){
    this.getUsers();
  },
  render:function(){
    return(
      <div style={{width:"300px"}}>
        <UserForm addUser={this.handleAddUser}/>
        <hr/>
        <UserList userData={this.state.userData}/>
      </div>
    );
  }
});
```

## Node.jsの実装
サーバーサイドも実装しましょう。

### ライブラリをインストール
まず手始めに、各種必要なライブラリをインストールします。
1.postされたデータを扱うために、`body-parser`というライブラリをインストールします。
2.postgreSQLと通信するために`pg`というライブラリをインストールします。

`$ npm install body-parser pg --save`

### pgのヘルパーjs作成
postgreSQLに接続してSQLを実行するまでの手続きは定型の処理のため、ヘルパー用のjsファイルを作ってしまいましょう。

```js:pghelper.js
var pg = require('pg'),
    databaseURL = 'postgres://postgres:{パスワード}@127.0.0.1:5432/postgres';

/**
 * poatgreSQLに接続してSQLを実行する
 * @param sql 実行したいSQL
 * @param values SQLに指定するパラメータ
 * @param callback SQL実行後、処理するイベント
 */
exports.query = function(sql, values, callback) {
  console.log(sql, values);

  pg.connect(databaseURL, function(err, conn, done) {
    if (err) {
      return callback(err);
    }
    try {
      conn.query(sql, values, function(err, res) {
        done();
        if (err) {
          callback(err);
        } else {
          callback(null, res.rows);
        }
      });
    } catch(e) {
      done();
      callback(e);
    }
  });
};
```

終わったら、usersの入出力を実装するためのjsファイルを作成します。
serverフォルダに、users.jsを作成します。

```js:users.js
var db = require('./pghelper');

/**
 * ユーザー一覧を取得します
 * @param req
 * @param res
 * @param next
 * @returns {*|ServerResponse}
 */
function getUsers(req, res, next) {
  db.query(
    'SELECT * FROM users',
    [], 
    function(err, datas){
      if (err){
        console.log(err);
        return res.status(400).send('エラーが発生しました');
      }
      return res.send(JSON.stringify(datas));
    }
  );
}

```
エラーが発生した場合、クライアント側にステータス400を返すとともに、「エラーが発生しました」というメッセージを返すようにします。

正常にデータが取得できた場合は、JSON形式で返されたデータをテキスト形式にして返します。

```js:users.js
/**
 * ユーザーを登録します
 * @param req
 * @param res
 * @param next
 * @returns {*|ServerResponse}
 */
function postUser(req, res, next) {
  var user = req.body;
  db.query(
    'INSERT INTO users (name, mail) VALUES ($1, $2) ',
    [user.name, user.mail], 
    function(err, datas){
      if (err){
        console.log(err);
        return res.status(400).send('エラーが発生しました');
      }
      return next();
    }
  );
}

exports.getUsers = getUsers;
exports.postUser = postUser;
```
ユーザー登録の場合、更新が成功したら、nextを実行します。nextにはgetUsersがserver.jsから指定される想定です。

次に、
server.jsを編集します。

```js:server.js
var express = require('express'),
    bodyParser = require('body-parser'),
    users = require('./users');
var app = express();
```
body-parserおよび、作成したusers.jsをインポートします。

```js:server.js
//ポートの指定
app.set('port', process.env.PORT || 5000);

//ルートパスの指定
var clientPath = __dirname.replace("/server", "/client");
app.use('/', express.static(clientPath));

//bodyParserの設定
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

//urlと呼びたいメソッドの紐付け
app.post('/post_user', users.postUser, users.getUsers);
app.get('/get_users', users.getUsers);
```
bodyParserの設定を行い、postで送られてきたデータを受け付けられるようにします。

また、クライアント側から指定したurlに応じたメソッドを実行できるように紐付けを行います。実行したいメソッドは複数指定できます。
上記では、postUserが終わったらgetUsersが呼ばれるようにしています。

ここまで実装したら、
jsxをコンパイル(`gulp browserify`)して、
サーバー起動(`node server/server.js`)し、
ブラウザで確認してみましょう。

ユーザーが登録できて、リストも再表示されればOKです。

# 捕捉
古いnodeのバージョンを使用している場合、インストールしたpgのバージョンとの対応関係により、接続エラーが発生する場合があります。
その場合は、pgのバージョンを固定してinstallしなおしてみてください。

```
//バージョンを固定してインストール
$ npm install pg@4.4.3 --save
```

# サンプルソース
https://github.com/kunitak/react-tutorial/tree/day7

次回→[今からはじめるReact.js〜画面遷移〜](http://qiita.com/kuniken/items/89c8bbef3b71d2af662d)