PIYO - Tech & Life -

MobXでTodoアプリ[Part1] MobX導入まで

ReactNative MobX

3部作のPart1です。

以前も書いたように、ここ1年ほどReact Nativeによるアプリ開発を時々行っています。凝ったアプリでなければ割とサクッと作れるのが良いです。

さてReact Native(というかReact)単体だとデータ管理が面倒、バケツリレーが云々という話がよくあります。その問題に対応すべく色々なFluxなフレームワークが存在していて、中でもReduxがよく使われるようになったという流れが2年前ぐらいにあったと記憶しています。

そういう流れで僕もReduxを使ってアプリ開発をしていましたが、ここ数ヶ月MobXというのをよく聞くようになりました。データ管理の用途だったらMobXで十分だよという話をよく見かけたようが気がするので、まずは試そうということでTodo的なアプリを作ってみることにしました。

GitHub - mobxjs/mobx-react: React bindings for MobX
React bindings for MobX. Contribute to mobxjs/mobx-react development by creating an account on GitHub.

結論としてはActionやらReducerやらを書かなくていいのでかなりシンプルになるなあという感想です。最低限動く状態を目指してTodoアプリを作るところをやってみようと重います。

ソースコードはタグを打って公開してあります。

GitHub - pi-chan/MobxTodoApp at part1
Contribute to pi-chan/MobxTodoApp development by creating an account on GitHub.

準備

アプリを作ったり、MobXを入れたりします。

  • % react-native init MobxTodoApp
  • cd MobxTodoApp
  • % npm install mobx mobx-react

Decoratorを使うためにbabelのプラグインをいれます。

  • % npm install babel-plugin-transform-decorators-legacy
  • .babelrcを以下のように変更
{
  "presets": ["react-native"],
  "plugins": ["transform-decorators-legacy"] // この行を追加
}

ストアを書く

TodoStoreというのを作って、追加と削除をできるようにしてみます。

MobxTodoApp/TodoStore.js at part1 · pi-chan/MobxTodoApp

import { observable, action } from 'mobx';

export default class TodoStore {
  @observable todos = [];

  @action.bound
  onAdd(todo) {
    this.todos = [...this.todos, todo];
  }

  @action.bound
  onDelete(todo) {
    this.todos = this.todos.filter(t => t !== todo);
  }
}
  • 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が居ます。

const todoStore = new TodoStore();
const stores = {
  todo: todoStore,
};

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <Provider {...stores}>
        <TodoScreen />
      </Provider>
    );
  }
}

最低限動いた様子

ステータスバーの下に潜っちゃってるのはご愛嬌。特に永続化していないのでリロードするたびに新たにストアが作られてデータ消えちゃいます。Part2では永続化のことを書いてみようかと思ってます。