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
から圧縮ファイルをダウンロードしてインストールします。
インストールしたら、起動してサーバーの追加を行います。
パスワードはpostgreSQLをインストールした際にpostgresユーザーに付与したパスワードのことです。
OKをクリックしたらサーバーが追加されます。
(Saving passwordsの画面が出たらOKをクリック)
usersテーブルを作成
postgresデータベースのpublicスキーマにusersテーブルを作成します。
「テーブル」ディレクトリを右クリックして、「新しいテーブル」をクリックします。
追加ボタンをクリックします。
プライマリーキーとなるidを追加します。データ型はserialとしておきます。
nameとmailについても以下のように追加します。
name
最後に、プライマリーキーを指定します。
OKボタンをクリックすると、以下のように表示されるはずです。
OKをクリックして設定を確定します。
下記のようにテーブルが作成されているはずです。
React.jsの実装
テーブルが作成できたら、ソースを書きましょう。body.jsxを編集します。
UserBoxコンポーネントの中にAjaxの処理を追記します。
今回実装したい処理としては、
・画面表示時にusersテーブルからデータを取得してリストに表示する
・追加ボタンをクリックした際にusersテーブルに入力データを追加してリストを最新データで再表示する
になります。
画面が表示された際になんらかのイベントを行いたい場合はcomponentDidMountメソッドを記述します。
更新するイベントは既存のhandleAddUserを編集するだけでいけそうですね。
//フォームとリストを一つにしたもの
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メソッドを実行するように書きます。
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メソッドを定義します。
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ファイルを作ってしまいましょう。
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を作成します。
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形式で返されたデータをテキスト形式にして返します。
/**
* ユーザーを登録します
* @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を編集します。
var express = require('express'),
bodyParser = require('body-parser'),
users = require('./users');
var app = express();
body-parserおよび、作成したusers.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
サンプルソース