Step4: コレクションを作成しよう!(Memos Collection)

このステップではMeteorのコレクションをReactと一緒に使用する方法を学びます。

Memos Collection

Meteorにはコレクション(Collection)という機能があります。

コレクションはデータベース(MongoDB)の操作APIを提供するもので、Meteorに標準で備わっている機能です。minimongoという仕組みにより、サーバーとクライントで同じAPIでMongoDB操作ができるようになっています。

このコレクション機能を使って、メモ用のデータを保存するコレクション(Memos Collection)を作成していきましょう。

imports/api/memos ディレクトリを作成し、その中に memos.js ファイルを作成します。

$ mkdir -p imports/api/memos
$ touch imports/api/memos/memos.js

imports/api/memos/memos.js

import { Mongo } from 'meteor/mongo';

export const Memos = new Mongo.Collection('Memos');

// for debug
if (Meteor.isDevelopment) {
  global.collections = global.collections || {};
  global.collections.Memos = Memos;
}

続いて、Memosコレクションの初期データを用意しましょう。

Memosコレクションが空だった場合に初期データを投入するコードを server/main.js に追加します。

server/main.js

import { Meteor } from 'meteor/meteor';
import { Memos } from '../imports/api/memos/memos';

Meteor.startup(() => {
  if (Memos.find().count() === 0) {
    const data = [
      {content: 'Memo 1'},
      {content: 'Memo 2'},
      {content: 'Memo 3'},
      {content: 'Memo 4'},
      {content: 'Memo 5'},
    ];
    data.forEach(memo => Memos.insert(memo));
  }
});

初期データを追加するため一度 meteor コマンドを Ctrl+C で終了させます。

# Ctrl+C

その後、再度 meteor コマンドを実行します。

meteor

初期データが追加されたかどうか確認するため、別のターミナルウィンドウを開き、Meteorアプリのディレクトリ内で以下のコマンドを実行します。

$ meteor mongo
MongoDB shell version: 2.6.7
connecting to: 127.0.0.1:3001/meteor
meteor:PRIMARY>

すると、MongoDBのシェル(REPL)が起動します。

Memosコレクションのデータを確認してみましょう。

meteor:PRIMARY> show collections;
Memos
system.indexes
meteor:PRIMARY> db.Memos.find();
{ "_id" : "KnpEcfkn9d9RsEiML", "content" : "Memo 1" }
{ "_id" : "9sBNyne4pYjwkvWXp", "content" : "Memo 2" }
{ "_id" : "Aop64vXHtXE2mFgf9", "content" : "Memo 3" }
{ "_id" : "H87FDebk9ominCPx8", "content" : "Memo 4" }
{ "_id" : "j3sN7YosasFBs8iCM", "content" : "Memo 5" }
meteor:PRIMARY> exit
bye

Memosコレクションにデータが追加されていますね!

それでは、Memosコレクションのデータをクライアント側で表示させましょう。

createContainer() - ReactMeteorData

Meteorのコレクションは「リアクティブデータソース」と呼ばれ、データが更新されると、その変更を通知する仕組みがあります。クライアント側でコレクションの変更を検知し、自動的にUIを書き換える仕組みを提供するのがreact-meteor-data Meteorパッケージです。

Meteor 1.2では react-meteor-data パッケージの ReactMeteorData mixin を使用することで、変更検知と画面の書き換えを自動で行っていました。

Meteor 1.3ではReactのmixinではなく、react-meteor-data が提供する createContainer()を使い、Meteorのリアクティブデータソースを管理する「コンテナ」を作ってコンポーネントをラップすることで、画面の自動更新を実現しています。

AppContainer

それでは早速ReactMeteorDataコンテナを作っていきます。

AppLayoutにMemosコレクションのデータを渡すための、AppContainerを作成します。

$ mkdir -p imports/ui/containers
$ touch imports/ui/containers/AppContainer.js

imports/ui/containers/AppContainer.js

import AppLayout from '../layouts/AppLayout';
import { Memos } from '../../api/memos/memos';
import { createContainer } from 'meteor/react-meteor-data';

export default createContainer(() => {
  return {
    memos: Memos.find().fetch(),
  };
}, AppLayout);

そしてAppLayoutを呼び出していた client/main.js を書き換えます。

client/main.js

import { Meteor } from 'meteor/meteor';
import React from 'react';
import { render } from 'react-dom';
import AppContainer from '../imports/ui/containers/AppContainer';

Meteor.startup(() => {
  render(
    <AppContainer />,
    document.getElementById('render-root')
  );
});

コードを書き換えると次のような表示になります。

なお、AppContainr を追加したことにより各コンポーネントの親子関係は次のようになります。

<AppContainer>
  <AppLayout>
    <Header />
    <MemoList>
      <MemoItem />
      <MemoItem />
      <MemoItem />
      ...
    </MemoList>
  </AppLayout>
</AppContainer>

Meteor ではコレクション等のリアクティブデータソースに関して、createContainer() で作成したコンテナでデータを管理し、各コンポーネントが必要なデータは親コンポーネントから子コンポーネントにデータを渡すようにすると、保守性・再利用性の高いコンポーネントになります。

複数クライアント間でのデータ同期

Meteorには標準でデータの同期機構が備わっています。また、データベース(MongoDB)のドキュメントが変更されると、それに対応するMeteorコレクションも自動的に変更される仕組みになっています。動きを確かめてみましょう。

すでに開いているWebブラウザとは別のWebブラウザウィンドウを開き、2画面で http://localhost:3000/ を表示させます。

その状態で、片方のWebブラウザのWebインスペクタを起動し、Consoleで以下のコマンドを入力します。

// Webインスペクタで実行
collections.Memos.insert({content: 'New Memo Data'})

上記コマンドを実行すると、メモリストにNew Memo Dataというデータが表示されます。また、もう一方のWebブラウザにもほぼ同時に同じデータが反映されます。

このように、Meteorではコレクションを使うことで、複数クライアント間でのデータ同期を簡単に実現できます。

次のステップへ進みましょう。

次へ