3部作のPart1です。
- MobXでTodoアプリ[Part1] MobX導入まで
- MobXでTodoアプリ[Part2] データを保存してみる
- MobXでTodoアプリ[Part3] Storeをデバッグしてみる
以前も書いたように、ここ1年ほどReact Nativeによるアプリ開発を時々行っています。凝ったアプリでなければ割とサクッと作れるのが良いです。
さてReact Native(というかReact)単体だとデータ管理が面倒、バケツリレーが云々という話がよくあります。その問題に対応すべく色々なFluxなフレームワークが存在していて、中でもReduxがよく使われるようになったという流れが2年前ぐらいにあったと記憶しています。
そういう流れで僕もReduxを使ってアプリ開発をしていましたが、ここ数ヶ月MobXというのをよく聞くようになりました。データ管理の用途だったらMobXで十分だよという話をよく見かけたようが気がするので、まずは試そうということでTodo的なアプリを作ってみることにしました。
結論としてはActionやらReducerやらを書かなくていいのでかなりシンプルになるなあという感想です。最低限動く状態を目指してTodoアプリを作るところをやってみようと重います。
ソースコードはタグを打って公開してあります。
準備
アプリを作ったり、MobXを入れたりします。
% react-native init MobxTodoAppcd MobxTodoApp% npm install mobx mobx-react
Decoratorを使うためにbabelのプラグインをいれます。
% npm install babel-plugin-transform-decorators-legacy.babelrcを以下のように変更
1{
2 "presets": ["react-native"],
3 "plugins": ["transform-decorators-legacy"] // この行を追加
4}
ストアを書く
TodoStoreというのを作って、追加と削除をできるようにしてみます。
MobxTodoApp/TodoStore.js at part1 · pi-chan/MobxTodoApp
1import { observable, action } from 'mobx';
2
3export default class TodoStore {
4 @observable todos = [];
5
6 @action.bound
7 onAdd(todo) {
8 this.todos = [...this.todos, todo];
9 }
10
11 @action.bound
12 onDelete(todo) {
13 this.todos = this.todos.filter(t => t !== todo);
14 }
15}
- todoはArrayで持つ
- onAddではArrayの末尾に新しい項目を追加
- onDeleteでは一致するものを削除
入力と一覧の画面を作る
MobxTodoApp/TodoScreen.js at part1 · pi-chan/MobxTodoApp
import { inject, observer } from 'mobx-react';
@inject('todo')
@observer
export default class TodoScreen extends Component {
render() {
// 略
}
}
@observerはプロパティの変更に応じて再描画するための指定で、@inject('todo')のところは、todoというストアをpropsにinjectするよの指定です。ざっくりいうと。ここは僕ももうちょとちゃんと理解しないと、な箇所です。
ともあれ、これでTodoStoreの内容を使えるようになるし、新しいTodoが追加されれば再renderされるようになりました。
renderの中身は省略しますが、適当にテキスト入力があって、todosの内容をFlatListで表示するというシンプルな内容になってます。
Providerで囲む
injectで各storeを使うためにはProviderを使うと便利です。。内部的にはReactのContextの仕組みが使われているようで、Provider配下のコンポーネントで使いたいストアを渡しておくと、配下のコンポーネントにinjectできるようになるという理解をしています。
MobxTodoApp/App.js at part1 · pi-chan/MobxTodoApp
storeを作ってProviderに渡してます。Provider配下には↑で作ったTodoScreenが居ます。
1const todoStore = new TodoStore();
2const stores = {
3 todo: todoStore,
4};
5
6type Props = {};
7export default class App extends Component<Props> {
8 render() {
9 return (
10 <Provider {...stores}>
11 <TodoScreen />
12 </Provider>
13 );
14 }
15}
最低限動いた様子
ステータスバーの下に潜っちゃってるのはご愛嬌。特に永続化していないのでリロードするたびに新たにストアが作られてデータ消えちゃいます。Part2では永続化のことを書いてみようかと思ってます。