Step5: メモの作成・削除ボタンを実装しよう!
このステップではMeteorコレクション追加・削除の仕方を学びます。
メモの新規作成
前のステップではWebインスペクタからメモデータを追加しました。今度はメモの新規作成ボタンを追加してみましょう。
AppLayoutとAppContainerを以下のように書き換えましょう。
imports/ui/layouts/AppLayout.js
import React from 'react';
import Header from '../components/Header';
import MemoList from '../components/MemoList';
export default class AppLayout extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick() {
const { memos, createMemo } = this.props;
createMemo(`New memo ${memos.length + 1}`);
}
render() {
const { memos } = this.props;
return (
<div className="container">
<Header />
<button className="add-button" onClick={this.onClick}>Add</button>
<MemoList memos={memos} />
</div>
);
}
}
AppLayout.propTypes = {
memos: React.PropTypes.array.isRequired,
createMemo: React.PropTypes.func.isRequired,
};
imports/ui/containers/AppContainer.js
import AppLayout from '../layouts/AppLayout';
import { Memos } from '../../api/memos/memos';
import { createContainer } from 'meteor/react-meteor-data';
const createMemo = content => {
Memos.insert({content});
};
export default createContainer(() => {
return {
createMemo,
memos: Memos.find().fetch(),
};
}, AppLayout);
ポイント
- Memosコレクションのデータを管理しているAppContainerでメモの新規作成を行う
createMemo()
を定義し、子コンポーネントのAppLayoutに渡す - AppLayoutはpropsを参照して、新規追加ボタンのイベント(onClick)を検知し、
createMemo()
を呼び出す
コードを書き換えたら、保存してWebブラウザを見てみましょう。
Addボタンが追加されていますので、何度か押してみてください。
Addボタンを押すたびに、新しいMemoデータが追加されます。
メモの削除
続いて、メモの削除機能を実装します。
まずAppContainerでremoveMemo()
を定義し、AppLayoutに渡します。
imports/ui/containers/AppContainer.js
import AppLayout from '../layouts/AppLayout';
import { Memos } from '../../api/memos/memos';
import { createContainer } from 'meteor/react-meteor-data';
const createMemo = content => {
Memos.insert({content});
};
const removeMemo = memoId => {
Memos.remove({_id: memoId});
};
export default createContainer(() => {
return {
memos: Memos.find().fetch(),
createMemo,
removeMemo,
};
}, AppLayout);
続いて、AppLayout, MemoList経由でMemoItemにremoveMemo()
を渡します。
imports/ui/layouts/AppLayout.js
import React from 'react';
import Header from '../components/Header';
import MemoList from '../components/MemoList';
export default class AppLayout extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick() {
const { memos, createMemo } = this.props;
createMemo(`New memo ${memos.length + 1}`);
}
render() {
const { memos, removeMemo } = this.props;
return (
<div className="container">
<Header />
<button className="add-button" onClick={this.onClick}>Add</button>
<MemoList memos={memos} removeMemo={removeMemo} />
</div>
);
}
}
AppLayout.propTypes = {
memos: React.PropTypes.array.isRequired,
createMemo: React.PropTypes.func.isRequired,
removeMemo: React.PropTypes.func.isRequired,
};
imports/ui/components/MemoList.js
import React from 'react';
import MemoItem from './MemoItem';
export default class MemoList extends React.Component {
render() {
const { memos, removeMemo } = this.props;
return (
<div className="memo-list">
{memos.map(memo => (
<MemoItem key={memo._id} memo={memo} removeMemo={removeMemo}/>
))}
</div>
);
}
}
MemoList.propTypes = {
memos: React.PropTypes.array.isRequired,
removeMemo: React.PropTypes.func.isRequired,
};
そしてMemoItemコンポーネントに削除ボタンを追加し、削除ボタンのonClick
にremoveMemo()
を設定します。
imports/ui/components/MemoItem.js
import React from 'react';
export default class MemoItem extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(event) {
event.preventDefault();
const { memo, removeMemo } = this.props;
removeMemo(memo._id);
}
render() {
const { memo } = this.props;
return (
<div className="memo-item">
<a href="#" onClick={this.onClick} className="remove-button">
×
</a>
<textarea className="textarea" defaultValue={memo.content} />
</div>
);
}
}
MemoItem.propTypes = {
memo: React.PropTypes.object.isRequired,
removeMemo: React.PropTypes.func.isRequired,
};
コードを書き換えたらブラウザで削除ボタンを試してみましょう!
メモの並び替え(作成日降順)
現在はメモを追加すると末尾に追加されます。少しわかりにくいですね。
新しいメモが作成日降順で表示されるように、並び替えましょう。
Memosコレクションのinsert時に作成日時を表すcreatedAt
フィールドを自動で追加するように変更します。
imports/api/memos/memos.js
import { Mongo } from 'meteor/mongo';
class MemosCollection extends Mongo.Collection {
insert(doc, callback) {
doc.createdAt = doc.createdAt || new Date();
const result = super.insert(doc, callback);
return result;
}
}
export const Memos = new MemosCollection('Memos');
// for debug
if (Meteor.isDevelopment) {
global.collections = global.collections || {};
global.collections.Memos = Memos;
}
ポイント
- Mongo.Collection を extends したES2015 classを作成する
- 必要に応じて
insert
,update
,remove
をオーバーライドする
これでMemosコレクション追加時にcreatedAt
フィールドが自動的に追加されるようになりました。
あとは、createdAt
降順でメモを表示するようにAppContainerのfind()
メソッドにオプションを設定します。
imports/ui/containers/AppContainer.js
import AppLayout from '../layouts/AppLayout';
import { Memos } from '../../api/memos/memos';
import { createContainer } from 'meteor/react-meteor-data';
const createMemo = content => {
Memos.insert({content});
};
const removeMemo = memoId => {
Memos.remove({_id: memoId});
};
export default createContainer(() => {
return {
memos: Memos.find({}, {sort: {createdAt: -1}}).fetch(),
createMemo,
removeMemo,
};
}, AppLayout);
コードを書き換えたらWebブラウザで動作確認します。
メモが作成日降順で表示されるようになりました。
次のステップに進みましょう。