Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

Simple, scalable state management
引用:https://mobx.js.org/

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

MobX Star.png

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ライフをお過ごしください。

sasaron397
プログラミングは雑食です。最近は、面白いと思ったものを色々と試しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした