10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

React-Native + MobXを動かす最小のサンプル

Last updated at Posted at 2018-06-22

ReactNativeとMobXを併存して動かすサンプルはそう多くなくあるが、ストアの注入とかのコードが理解しづらかったのと、react向けの記事では動かない部分もあったりするので最小限のコードでMobXを動かしてみるという方法をメモしておく。

MobXとはなにか

これは初心者の雑な理解。
ReactではUIパーツをコンポーネントという単位で開発する。コンポーネントはステートを持つことも可能だけれども、一般的な話だがステートを持つとテストしにくいとか、ステートの場所が散らばって管理が大変とかいう問題がある。
そこでその状態をもつ箇所を一箇所に集めてインターフェイスを統一する機構としてReduxという実装を用いるのがReactでは一般的になっている。

結局FluxやらReduxやらって何なのか個人的なまとめ

しかし、Reduxで実装するために書かなければならないコードが多く煩雑なため見通しもあまり良くなかったり、ボイラープレート的なものを書く必要が多かったりして覚えるのが大変だし使うのも面倒という点で初心者にはツラいと言われている気がする。

そこでもっと記述量を減らした便利なステート管理をするツールとしてMobXというのが使われる。しかし日本ではあまりMobXの採用事例がないっぽく、解説記事が英語の記事ばかりでそれはそれで初心者にはツラいなあみたいな状況がある気がする。

環境

react-native-cli: 2.0.1
react-native: 0.55.4
node 8.11.1

https://facebook.github.io/react-native/docs/getting-started.html
ここを参考に環境構築する。本筋ではないが、Building Projects with Native Codeの方で作成している(Quick Startだとネイティブ実装が必要でも書くことができないため)
以下、 react-native init ${プロジェクト名}で作成したscaffold上での作業として記載している。

必要なパッケージをインストール

yarn add mobx # mobx本体
yarn add mobx-react # mobxをreact上で使うのを楽にしてくれるなにか
yarn add babel-preset-react-native-stage-0 # mobxのコードを書くときデコレーター(Javaでいうアノテーション的ななにか)を使用しているためこれを解釈するために必要

babelの設定を追加

.babelrc
{
  "presets": ["react-native", "react-native-stage-0/decorator-support"]
}

特に何もしなければ presetsの中はreact-nativeしかないが、これにインストールした react-native-stage-0/decorator-supportを追加してデコレーターを使用可能にする。

Storeを作成する

MyStore.js
import {
  observable,
  action
} from 'mobx'

class MyStore {
  @observable num = 0;

  @action.bound async incrementAsync() {
    await new Promise((resolve) => {
      setTimeout(() => {
        this.num += 1;
        resolve();
      }, 1000)
    });
  }
}

const mofu = new MyStore()
export default mofu;

@observableを付与した値はこの値が変更されたときに、これをobserveしているコンポーネントに変更が通知され、当該コンポーネントが再描画されるようになっている。

@action.boundを使用するとobservableな値を加工する関数を書くことができる。今回はsetTimeoutとPromiseを使用した疑似非同期メソッドを作成したが、axiosなどで非同期にインターネット経由で値を書き込むといった使い方がユースケースとして想定される。

コンポーネント側で読み取る

App.js
import React, { Component } from 'react';
import {
  Button,
  Text,
  View
} from 'react-native';
import { observer } from 'mobx-react/native'
import MyStore from './MyStore'

type Props = {};

@observer
export default class App extends Component<Props> {
  render() {
    return (
      <View>
        <Text>{MyStore.num.toString()}</Text>
        <Button onPress={MyStore.incrementAsync} title="countUp"/>
      </View>
    );
  }
}

@observer はコンポーネント内で使用するストアに属するobservableな値の変更を検知したい場合に付与する。こうすると値が変更されたときに、ストアの値を使用しているコンポーネントがプロパティを置き換えて再描画される。

動作イメージ

Jun-22-2018 12-56-43.gif
初期状態で、Textはストアの値(num=0)を表示している。ボタンを押すとStoreのincrementAsyncメソッドが呼び出され、1秒後にnumの値が1増えた状態に書き換えられる。その変更がTextに通知され、Textの中の値が書き換わった状態で再描画されている。

10
6
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
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?