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

  • 70
    Like
  • 0
    Comment

前回→今からはじめるReact.js〜仮想環境を作成する〜

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
パスワードはpostgreSQLをインストールした際にpostgresユーザーに付与したパスワードのことです。

OKをクリックしたらサーバーが追加されます。
(Saving passwordsの画面が出たらOKをクリック)
スクリーンショット 2015-10-16 16.38.49.png

usersテーブルを作成

postgresデータベースのpublicスキーマにusersテーブルを作成します。
「テーブル」ディレクトリを右クリックして、「新しいテーブル」をクリックします。
スクリーンショット 2015-10-16 16.40.46.png

テーブル定義は以下の通りです。
スクリーンショット 2015-10-16 16.42.07.png

「列」をクリックして、カラムの追加を行います。
スクリーンショット 2015-10-16 16.43.37.png

追加ボタンをクリックします。
プライマリーキーとなるidを追加します。データ型はserialとしておきます。
スクリーンショット 2015-10-16 16.45.30.png

nameとmailについても以下のように追加します。
name
スクリーンショット 2015-10-16 16.47.17.png

mail
スクリーンショット 2015-10-16 16.48.19.png

こんな感じになります。
スクリーンショット 2015-10-16 16.48.51.png

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

「制約」で追加ボタンをクリックします。
スクリーンショット 2015-10-16 16.49.43.png

プロパティは、以下のようにします。
スクリーンショット 2015-10-16 16.50.59.png

列でidを指定して追加ボタンをクリックします。
スクリーンショット 2015-10-16 16.52.15.png

OKボタンをクリックすると、以下のように表示されるはずです。
スクリーンショット 2015-10-16 16.53.05.png

OKをクリックして設定を確定します。
下記のようにテーブルが作成されているはずです。
スクリーンショット 2015-10-16 16.55.08.png

React.jsの実装

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

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

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

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メソッドを実行するように書きます。

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メソッドを定義します。

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は省略しても実行できます。

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

//フォームとリストを一つにしたもの
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ファイルを作ってしまいましょう。

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を作成します。

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形式で返されたデータをテキスト形式にして返します。

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を編集します。

server.js
var express = require('express'),
    bodyParser = require('body-parser'),
    users = require('./users');
var app = express();

body-parserおよび、作成したusers.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〜画面遷移〜