タグ別アーカイブ: superagent

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

※この記事は
http://qiita.com/kuniken/items/bc20fd1e907d91b641d6
で投稿した内容と同じものです。

前回→今からはじめる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
から圧縮ファイルをダウンロードしてインストールします。

インストールしたら、起動してサーバーの追加を行います。
postgre1
パスワードはpostgreSQLをインストールした際にpostgresユーザーに付与したパスワードのことです。

OKをクリックしたらサーバーが追加されます。
(Saving passwordsの画面が出たらOKをクリック)
postgre2

usersテーブルを作成

postgresデータベースのpublicスキーマにusersテーブルを作成します。
「テーブル」ディレクトリを右クリックして、「新しいテーブル」をクリックします。
postgre3

テーブル定義は以下の通りです。
postgre4

「列」をクリックして、カラムの追加を行います。
postgre5

追加ボタンをクリックします。
プライマリーキーとなるidを追加します。データ型はserialとしておきます。
postgre6

nameとmailについても以下のように追加します。
name
postgre7

mail
postgre8

こんな感じになります。
postgre9

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

「制約」で追加ボタンをクリックします。
postgre10

プロパティは、以下のようにします。
postgre11

列でidを指定して追加ボタンをクリックします。
postgre12

OKボタンをクリックすると、以下のように表示されるはずです。
postgre13

OKをクリックして設定を確定します。
下記のようにテーブルが作成されているはずです。
postgre14

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です。

サンプルソース

https://github.com/kunitak/react-tutorial/tree/day7

次回→今からはじめるReact.js〜画面遷移〜