LoginSignup
20
23

More than 5 years have passed since last update.

Meteor + react + react router入門

Posted at

Meteor.jsとは

node.jsのフルスタックフレームワーク。なにかプロトタイプを作ろうと思った時にさくっと作ることができます。リアルタイムwebアプリが作れで、リアクティブにデータが反映されます。
これは、ページをリロードしなくても、データの更新があれば該当の値が更新されるものです。チャットアプリのような挙動です。それがチョー簡単につくれます。

React.jsとは

FacebookがOSSとして公開していて、実際にプロダクトにも使用しているフロントエンドのフレームワークです。スタートアップ界隈でもよく使われています。このReactの概念さえ覚えてしまえば、React Nativeをつかってネイティブアプリの構築もすることができます。

参考:出来る限り短く説明するReact.js入門

Meteor インストール (MAC)

これをターミナルで叩く

curl https://install.meteor.com/ | sh

Meteor プロジェクト作成

プロジェクトを起きたいディレクトリまで移動して、
meteor create "アプリ名"で作成

meteor create sample-meteor-react

Meteor 起動

プロジェクトのディレクトリに移動して、”meteor”と打てばサーバー起動

cd sample-meteor-react
meteor

http://localhost:3000/を開いて、”Welcome to Meteor!”の画面が表示されていれば成功

React インストール

meteor npm install --save react react-dom

セキュリティ上問題のある2つのパッケージを削除

meteorにはデフォルトでinsecureautopublishというパッケージが入っています。insecureはサイトに訪れたすべての人がDBを操作できるように初期設定されているもので、autopublishもサイトに訪れた人がすべての人がすべてのデータを見れるようにしているものです。
本番環境ではデータの閲覧、操作権限誰にでもできないようにサーバーサイドでチェックを入れるのですが、meteorは公開前のプロトタイピングがしやすいように、このような権限を全開放する初期設定になっています。
いずれ消すので、とっととその2つを消し去りましょう。

meteor remove insecure
meteor remove autopublish

既存のテンプレートを削除

meteorにはデフォルトでblazeというテンプレートが入っています。今回はReactを使用するのでこちらを削除します。

meteor remove blaze-html-templates
meteor add static-html

React用にMeteorのファイルを変更

main.htmlを変更

id="render-target"の中にreactの要素が流し込まれます。

client/main.html
<head>
  <title>sample-meteor-react</title>
</head>

<body>
  <div id="render-target"></div>
</body>

main.jsを変更

client/main.js
import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';

import RouteApp from '../imports/router/RouteApp.jsx';

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

ここのRouteAppというのは後で作る、ルーティング用のReactコンポネントです。今の段階でページにアクセスするとエラーが出るのですが、気にせんといて次に進んでください。

React用のディレクトリ作成

importsフォルダを作成、中身はこのような感じ

imports/
  ├ router
  ├ ui
     └ components
     └ pages

react-router-domインストール

https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom

npm install --save react-router-dom

react routerを設定

router/RouteAppを編集

router/RouteApp.jsx
import React, {Component} from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch,
} from 'react-router-dom';
import Top from '../ui/pages/Top.jsx';
import AnotherPage from '../ui/pages/AnotherPage.jsx';

export default class RouteApp extends Component{
  render(){
    return(
      <Router>
        <Switch>
          <Route exact path="/" component={Top}/>
          <Route exact path="/another" component={AnotherPage}/>
        </Switch>
      </Router>
    )
  }
}

これでルーティングの設定は完了です。
他のページを追加したいときも<Switch></Switch>の中に
<Route exact path="パス" component={表示するコンポネント}/>
の形で追加していけばよいです。シンプルですね。

Reactコンポネント作成

imports/ui/pagesの中に

  • Top.jsx
  • AnotherPage.jsx

を作成します。

imports/ui/pages/Top.jsx
import React, {Component} from "react";

export default class Top extends Component{
  render(){
    return(
      <div>topページ</div>
    )
  }
}
imports/ui/pages/AnotherPage.jsx
import React, {Component} from "react";

export default class AnotherPage extends Component{
  render(){
    return(
      <div>違うページ</div>
    )
  }
}

ページ確認

これで、
http://localhost:3000/
http://localhost:3000/another
にアクセスして、さっき作ったページが表示されていればOKです!
ページ遷移はこれで完璧です。

Meteorでのデータの扱い

ここからは、meteorでのデータの扱うために、サンプルでto doアプリを作成します。

collectionの作成

collectionとは、SQLのテーブルのようなものです。
- imports/apiフォルダを作成
- apiフォルダの中にcollections.jsを作成

imports/api/collections.js
import {Mongo} from 'meteor/mongo'

export const Todos = new Mongo.Collection('todo');

これをserver/main.jsにてimport

server/main.js
import { Meteor } from 'meteor/meteor';
import '../imports/api/collections.js';

Meteor.startup(() => {
  // code to run on server at startup
});

Methodの作成

collectionが作成できたので、次はメソッドの作成です。
メソッドとは、実査にDBへの処理記述するもので、MVCでいうモデルに該当します。

  • imports/api/にmethods.jsを作成
imports/api/methods.js
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { Todos } from './collections.js';

Meteor.methods({
  'addTodos'(){
    todo = {
      date:new Date(),
      content:"test!"
    };
      Todos.insert(todo);
  },
})

ここでは、todoリストにデータを挿入するメソッドを作成しました。

そして、コレクションのときと同じようにserver/main.jsにてimport

server/main.js
import { Meteor } from 'meteor/meteor';
import '../imports/api/collections.js';
import '../imports/api/methods.js';

Meteor.startup(() => {
  // code to run on server at startup
});

メソッドを実行する方法

Top.jsxを以下のように編集します

imports/ui/pages/Top.jsx
import React, {Component} from "react";

export default class Top extends Component{
  addTodo(){
    Meteor.call('addTodo')
  }

  render(){
    return(
      <div>
        <div>topページ</div>
        <a onClick={(e)=>this.addTodo(e)}>to do リストに追加</a>
      </div>
    )
  }
}

これで、to do リストに追加をクリックすれば、データが追加できるようになりました。

データの表示

Meteorはリアクティブなフレームワークです。ですが、全ての情報をクライアント側に送るわけにはいかないので、どの情報を送るかどうかをこちらで管理しなければいけません。それを制御するために、以下のファイルを作成します。

impots/api/server/main.js
import { Meteor } from 'meteor/meteor';
import { Todos } from '../collections.js';

if(Meteor.isServer){
  Meteor.publish('getTodos', function(){
     return Todos.find({});
  });
}

今回はすべてのtodoリストをクライアント側に返すものを作成しました。
返したいものをreturnするだけです。

また、これもserver/main.jsにimportします

server/main.js
import { Meteor } from 'meteor/meteor';
import '../imports/api/collections.js';
import '../imports/api/methods.js';
import '../imports/api/server/publications.js';

Meteor.startup(() => {
  // code to run on server at startup
});

to doリストの表示

MeteorのデータをReactに流し込むためには、withTrackerを使えるようにする必要がります。そのためにreact-meteor-dataをインストール

meteor add react-meteor-data

今回はtopページに表示するので、Top.jsxを以下のように編集

imports/ui/pages/Top.jsx
import React, {Component} from "react";
import { withTracker } from 'meteor/react-meteor-data';
import {Todos} from '../../api/collections.js';

class Top extends Component{
  addTodo(){
    Meteor.call('addTodo')
  }

  renderTodos(){
    let todos = this.props.todos;
    if(todos){
      return todos.map((todo,index)=>{
        return(
          <li key={index}>
            {todo.content}
          </li>
        );
      });
    }
  }

  render(){
    return(
      <div>
        <div>topページ</div>
        <a onClick={(e)=>this.addTodo(e)}>to do リストに追加</a>
        <ul>
        {this.renderTodos()}
        </ul>
      </div>
    )
  }
}

export default withTracker(()=>{
  let todos;

  if(Meteor.subscribe('getTodos').ready()){
    todos = Todos.find().fetch();
  }

  return{
    todos:todos
  }
})(Top);

withTrackerでreturnしたデータはpropsとして参照することができます。
先程、定義したものを

imports/api/server/publication.js
Meteor.publish('getTodos', function(){
     return Todos.find({});
  });

このように呼び出すことができます。
Meteor.subscribe('getTodos')

また、ready()をつけることによって、データのsubscribeの準備ができたかどうかを確認しています。react + meteorの組み合わせだと、このサブスクライブの準備ができるまでに一回renderされるので、チェックが必要です。

これで、”to do リストに追加”をクリックする度にどんどん”test!”という項目が追加されていっているかと思います。

Methodに引数を渡して、入力した値をDBに格納

このままだと、同じ文章が並ぶので、入力欄を設けて、メソッドに引数を渡して処理をする方法がこちらです。

まずはformを作成し、送信できるようにTop.jsxを修正

imports/ui/pages/Top.jsx
import React, {Component} from "react";
import { withTracker } from 'meteor/react-meteor-data';
import {Todos} from '../../api/collections.js';

class Top extends Component{
  constructor(props){
    super(props);
    this.state = {
      todoText:"",
    }
  }

  addTodo(){
    Meteor.call('addTodo')
  }

  renderTodos(){
    let todos = this.props.todos;
    if(todos){
      return todos.map((todo,index)=>{
        return(
          <li key={index}>
            {todo.content}
          </li>
        );
      });
    }
  }

  submitForm(e){
    e.preventDefault();
    let todoText = this.state.todoText;
    Meteor.call('addTodo',todoText);
  }

  render(){
    return(
      <div>
        <div>topページ</div>


        <form onSubmit={(e)=>this.submitForm(e)}>
          <input type="text" onChange={(e)=>this.setState({todoText:e.target.value})} value={this.state.todoText}/>
          <input type="submit" value="リストに追加"/>
        </form>
        <a onClick={(e)=>this.addTodo(e)}>to do リストに追加</a>
        <ul>
        {this.renderTodos()}
        </ul>
      </div>
    )
  }
}

export default withTracker(()=>{
  let todos;

  if(Meteor.subscribe('getTodos').ready()){
    todos = Todos.find().fetch();
  }

  return{
    todos:todos
  }
})(Top);

次に、methods.jsも変更

imports/api/methods.js
import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { Todos } from './collections.js';

Meteor.methods({
  'addTodo'(content){
    var todo = {
      date:new Date(),
      content:content
    };
    Todos.insert(todo);
  },
})

メソッドは第二引数以降で、引数を渡せます。
Meteor.call('メソッド名',args...)

また、Meteor.subscribeも第二引数以降で引数を渡せます。
Meteor.subscription('パブリッシュ名',args...)

完成

これで自由に値の入力ができるようになりました。
todoリストとしては編集も削除もできず、すべてのユーザに同じものが表示されるゴミですが、
reactでイベント作る→メソッドを作成してそれを呼び出す→メソッド内でmongoDBを操作
で同じようにDBの処理ができ、
表示したいデータをpublication.jsで定義→それを使用するページでMeteor.subscribe('publications.js定義した関数名')で呼び出し
でデータの受け取りを行うことができます。
例えば、指定したuserIdのtodoしかか表示しない場合は、Meteor.subscribeにuser引数を渡して、

Meteor.publish('getTodos', function(userId){
     return Todos.find({userId:userId});
  });

のようにすればOkです。

まとめ

meteorの解説中心となってしまいました。Reactは他の方々がわかりやすい説明をしているので、ググってそちらを見ていただくほうが良いですな。
React + meteor + react routerの組み合わせはこのようにサクッとプロダクトを作れるので、まだまだ駆け出しで、jsしか知らない人がさくっと高速開発するのにはおすすめです。(ただ、デプロイちょっと面倒です。今度書きます。)
あとは、使う場面があれば、リアルタイムDBもすごく魅力的。

今回のコードはこちらです。
https://github.com/keitaisozaki/sample-meteor-react

日本はあまり使っている人に出会ったことがないのですが、使う人増えたら嬉しいです:relaxed:

20
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
23