MeteorJSとReactを勉強してみる その3: コレクションにタスクのデータを蓄積しよう【公式翻訳】
MeteorJSを勉強するシリーズ第三回です。
翻訳しながら、やっぱり完全な初心者にはわからないことだらけな気がするので、気が向いたらそのへんのケアも出来る記事に後から改変していきます。
コレクションにToDoタスクのデータを蓄積する
コレクションとはMeteorで永続的なデータを蓄積する方法です。
Meteorのコレクションの素晴らしい点は、サーバー・クライアント双方からアクセス可能であり、サーバー側のコードを頑張って書かなくてもViewロジックを簡単に書ける、ということです。
さらにコレクションは自動的に更新されるので、コレクションを利用して書かれたViewコンポーネントは常に最新のデータを表示することができます。
もっと詳しく知りたい方は、Meteor Guideのコレクションの記事を読んでみてください。
新しいコレクションを作るには、JavaScript内でMyCollection = new Mongo.Collection("my-collection");
を宣言するだけでOKです。
上記をクライアント側で書くと、サーバー側のコレクションと繋がったキャッシュが作成されます。
本チュートリアルのStep.12ではクライアントとサーバーの分割についてより詳細に解説しますが、現時点では「全てのデータベースがクライアントに表示される」という前提でコーディングしていきましょう。
コレクションを作るため、下記の通りに新しいフォルダとファイル(tasks モジュール)をimports配下に作成しましょう。
imports/api/tasks.js
import { Mongo } from 'meteor/mongo'; export const Tasks = new Mongo.Collection('tasks');
ここではimports/api
という新しいディレクトリを作成し、その中にtasks.js
を作成しました。
imports/api
はアプリケーションのAPI関連のファイルを置くための重要な場所です。
まずはここにコレクションをおいておき、後でこれらのコレクションから読み込みを行うpublication
と、書き込みを行うmethods
を追加していきます。
アプリの構造について、詳しくはMeteor GuideのApplication Structure articleを読みましょう。
このtasksモジュールは、サーバー側で読み込んであげる必要があります。これによりMongoDBのコレクションが作成され、クライアント側にデータを提供する「配管工事」が完了するわけです。
before
import { Meteor } from 'meteor/meteor'; Meteor.startup(() => { // code to run on server at startup });
after
import '../imports/api/tasks.js';
Reactコンポーネント内でコレクションデータを利用する
Reactコンポーネントの中でMeteorコレクションのデータを利用するには、Atmosphereのパッケージであるreact-meteor-data
を活用しましょう。
このパッケージにより、Meteorのreactive dataをReactコンポーネントの階層内で読み込むことのできる「データコンテナ」を作成することができます。
ターミナルで下記のコマンドを打ちましょう。
meteor add react-meteor-data
実際にreact-meteor-data
を利用するには、作成したコンポーネントをwithTracker
と言うより高位のコンポーネントを利用したコンテナで包んであげる必要があります。
imports/ui/App.js
before
import React, { Component } from 'react'; import Task from './Task.js'; // App Component - represnts the whole app export default class App extends Component { getTasks() { return [ { _id: 1, text: 'This is task 1' }, { _id: 2, text: 'This is task 2' }, { _id: 3, text: 'This is task 3' } ]; } renderTasks() { return this.getTasks().map((task) => ( <Task key={task._id} task={task} /> )); } render() { return ( <div className="container"> <header> <h1>Todo List</h1> </header> <ul> {this.renderTasks()} </ul> </div> ); } }
after
import React, { Component } from 'react'; import { withTracker } from 'meteor/react-meteor-data'; import { Tasks } from '../api/tasks.js'; import Task from './Task.js'; // App Component - represnts the whole app class App extends Component { renderTasks() { return this.props.tasks.map((task) => ( <Task key={task._id} task={task} /> )); } render() { return ( <div className="container"> <header> <h1>Todo List</h1> </header> <ul> {this.renderTasks()} </ul> </div> ); } } export default withTracker(() => { return { tasks: Tasks.find({}).fetch(); }; })(App);
withTrackerで包まれたAppコンポーネントはTasksコレクションからタスクを取得し、それをタスクpropとして元々のAppコンポーネントに提供しています。
これらのコードはデータベースの変更に対して受動的に動きます。つまり、データベースのコンテンツが変更されるとAppが再読み込みされるようになります。
さて、上記のとおりにコードを変更したら、元々Todoリスト内にあったタスクが消えてしまったのに気づいたでしょうか?
それはデータベースが空のままだからです。いくつかデータベースにタスクを追加してみましょう!
サーバーサイドのデータベース管理画面からタスクを追加する
コレクション内のアイテムは「ドキュメント」と呼びます。 サーバーのデータベース管理画面から、コレクションにドキュメントを追加してみましょう。
新しくターミナルのタブを開いて、アプリのディレクトリまで移動し、下記のコマンドを打ってください。
meteor mongo
これでアプリのローカル開発環境のデータベースに接続できました。 ターミナルに下記の通りに打ち込んでください。
db.tasks.insert({ text: "Hello world!", createdAt: new Date() });
ブラウザで確認すると、アプリのUIが即座に変更され、新しいタスクが表示されました。
サーバーサイドのデータベースをフロントエンドのコードに繋ぐためのコードを書く必要が無かったことが分かりますね。 これらはMeteorが内部的に自動で処理しているのです。
上記と同様に、ターミナルから違うテキストでいくつかタスクを追加してみてください。 次のステップでは、ターミナルを使わずにアプリのUI上からタスクを追加することができるように機能を追加していきます。
今回は以上です。
JavaScriptの言語仕様を知らない場合、最後のimports/ui/App.js
の変更内容を理解するのは鬼門かもしれませんね・・・
とは言え僕も解説できるほどではないので、折を見てちゃんと記事を更新したいと思います。
次回の更新は来週になります。