Edited at

React.js + MobX アーキテクチャによるお手軽フロントエンド実装

More than 1 year has passed since last update.

MobXは、シンプルでありながら拡張性を備える状態管理モジュールです。


Simple, scalable state management

引用:https://mobx.js.org/


GitHubのスター数は1万弱ですが、順調に伸びており、流行の兆しを見せています。


MobX は React コミュニティ内でとても人気になってきており

引用:https://jp.vuejs.org/v2/guide/comparison.html#MobX-%E3%81%A8%E7%94%A8%E3%81%84%E3%81%9F%E5%A0%B4%E5%90%88


私も実際に使ってみましたが、本当にシンプルでした。学習コストが低いので、すぐに開発を始めることができます。


MobXのサンプル

MobXのお手軽さを体感するために、簡易的なサンプルを作成しました。

下記のコードは、1秒ごとにデータストアが持つ現在時刻を最新化した上で、React側に通知してレンダリングするサンプルです。

注目すべき点は @observable@observer です。

仕組みは単純で、@observableの付いた値を監視して、変更があれば@observerに更新を通知します。

最低限、これだけ理解すればスタートすることができます。かなりお手軽ですね。


NowDateStore.jsx(現在時刻のデータストア)

// https://github.com/mobxjs/mobx

import {observable} from "mobx";
// [日付モジュール] https://momentjs.com/
import moment from "moment";

class NowDateStore {
// @observable があるので監視対象です。重要なのはここだけです。
@observable nowDate = "";

constructor() {
// 1秒ごとに現在日時を更新します
setInterval(() => { this.refreshNowDate(); }, 1000);
}

refreshNowDate() {
// 端末の現在日時をセットします
// Like a 2017-08-30T01:00:24+09:00
this.nowDate = moment().format();
}
}

export default NowDateStore;



Test.jsx(ReactComponent)

import React from "react";

import PropTypes from 'prop-types';
import {observer} from "mobx-react";

// @observerがついているため、MobXから更新の通知を受信します。
// 更新を受信するとrenderが走ります。
@observer class Test extends React.Component {
// SEE: https://github.com/mobxjs/mobx-react
componentWillReact() {
console.log("I will re-render, since the now date has changed!");
}

render() {
return (
<p>現在時刻:{this.props.nowDateStore.nowDate}</p>
);
}
}

Test.propTypes = {
nowDateStore: PropTypes.object
};

export default Test;



index.jsx

import ReactDOM from 'react-dom';

// データストアのインスタンスを生成
const nowDateStore = new NowDateStore();

// 生成するコンポーネントに渡しておき、データストアに簡単にアクセスできるようにしておく
ReactDOM.render(
<Test nowDateStore={nowDateStore} />,
document.getElementById("test")
);


上記のサンプルは最低限です。

例えば、observableの生成パターンも実際には複数存在します。


  • observableで包んで生成するパターン: observable(value)

  • デコレータを付与するパターン: @observable

また、専用の PropTypesが用意されていたりもします。

以下のサイトが参考になりましたので、ぜひ参照してください!


どのJSを採用するのか

これは私の個人的な見解ですが、WebプロダクトでJSを採用する場合、概ね3つのステージに分けられるのではないかと感じています。


  • ステージ1:フォームの内容を書き換えるといった簡易的なJS(jQueryやピュアJSで十分)

  • ステージ2:特定の画面のみレンダリングが必要など、限定的に使用するケース(リアクティブなレンダリングや状態管理が必要だけれども、SPAという程ではない)

  • ステージ3:SPA(Single Page Application)

このうち、MobXパターンが最適なのは「ステージ2」だと思います。React.js に MobX をかませることで、データストアの分離がやりやすくなり楽することが出来ます。


MobXの利点


1.覚えやすく使いやすい

2.書くコード量が減る

3.オブジェクト指向プログラミングの完全サポート

4.ネストデータの取り扱いが簡単

引用:https://www.webprofessional.jp/redux-vs-mobx-which-is-best/


ただ、シンプルすぎるので、大規模プロダクトで採用するとReduxのようなキッチリ分割した実装より混乱を招きやすいと思います。そういう意味では、あまり学習コストや実装コストをかけずに作りきってしまいたい小〜中規模向けになりますね。


MobXの欠点

前項でも触れましたが、MobXは完璧な魔法の呪文ではなく、欠点も勿論存在します。


1.自由度がありすぎる

2.デバッグが難しい

3.MobXよりも良い選択肢があるかもしれない

引用:https://www.webprofessional.jp/redux-vs-mobx-which-is-best/


特に自由度の高さは、簡単に実装できる代償としてのトレードオフでもありますが。

規約や設計の領域でカバーするしかないかもしれません。

この辺りの話はりぃさんの記事が非常に参考になりました。

http://lealog.hateblo.jp/entry/2017/03/08/114017


Vue.jsと似ているらしい

私はVue.jsに触れたことはないのですが、実はVue.jsに似ているらしいとサイトに記載されています。


MobX は React コミュニティ内でとても人気になってきており、実はそれは Vue のリアクティブシステムとほぼ同じものを使っています。限られた範囲内では、React + MobX の流れはより冗長な Vue として考えることができるので、もしあなたがその組み合わせを使って、それを楽しんでいるのならば、Vue を使ってみるのは、おそらく次のステップとして理にかなっているでしょう。

引用:https://jp.vuejs.org/v2/guide/comparison.html#MobX-%E3%81%A8%E7%94%A8%E3%81%84%E3%81%9F%E5%A0%B4%E5%90%88


つまり、React.js を Vue.js のようにしたのが MobX であるということなのでしょうか。

私は「React + MobX」がしっくりきましたので、Vue.jsも試してみようと思います。


まとめ

「React.js + MobX」によるアーキテクチャは、以下のようなユースケースに適していると感じました。


  • React.js単体で使用するだけだと厳しい

  • Reduxをきっちり理解して実装する程の学習コストや実装コストを払える規模の案件ではない

  • コード量は増やさずにさくっと開発したい

何より MobXは30分もあれば簡単な使い方を理解できますので、即効性のある選択肢の一つとして良さげだなといった印象です。

それでは、みなさま良いJSライフをお過ごしください。