Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

前回→今からはじめる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〜画面遷移〜

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away