読者です 読者をやめる 読者になる 読者になる

console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

0からはじめる MobX Part.1

海外では去年くらいからRedux alternativeとして割と名前が上がってると思うのですが、国内はまだまだもっぱらReduxですねー。

個人的には何でもいいんですけど、Reduxはもう色んな人がやってるし、自分は違う方面を掘ってみたいなーと思いつつ、
いつまでたっても仲間が増える気配がないので、自分で布教していくことにした次第!

ちなみに、趣味案件ではもう使ってて、仕事案件でも使ってみようかなーくらいの熟練度です。

なにこれ

@mweststrate氏作の、いわゆるState managementに使うライブラリ。

Anything that can be derived from the application state, should be derived. Automatically.

という哲学のもとに生まれたらしい。

コード見たほうがいろいろ早いと思うのでありそうなコードの要点を書くと、このように。

// Observableな値を用意して
const appState = observable({
    timer: 0
});

// Observerとして指定したReactのViewで受ければ
const TimeView = observer(class TimerView extends React.Component {
  render() {
    return (
      <div>
        Seconds passed: {this.props.appState.timer}
      </div>
    );
  }
});

// データを直接!更新するだけでViewに反映される
setIterval(() => {
  appState.timer++;
}, 1000);

簡単!便利!これがFRPってやつなんですかね?
ちなみにソースはTypeScriptでカッチカチで、なにげに1年以上前から開発されてて、毎日Issueの対応とかしてて、とにかく盛んな感じです。

というわけでまったくのRedux Alternativesではなくて、あくまでStateとViewの紐付けがいい感じになるやつです。
Fluxライクなデータフローにしたいなら自分でそう書きます。

導入

こんな書き出しですが、Reactは必須じゃないです。
ただだいたいはReactと一緒に使いたいと思うので、今回はそのていで。

npm i mobx mobx-react --save

ちなみにこのライブラリ、Decoratorsを使ったサンプルが山ほどでてきますが、これも別に必須じゃないです!
全機能に、ちゃんと代わりの記法があります。

ただDecoratorsを使ったほうがいろいろすっきり書けるので、まだStage 2ですがそこはお好みで。

ドキュメントはむちゃくちゃ充実してるので、一通り目を通しておくと吉。

Introduction | MobX

最低限知っておけばいいこと

Observableな値の作り方

// プレーンなオブジェクト
const store = observable({
  a: 1,
  b: '2',
  c: [3, 4, 5],
});

// クラス
function Todo(title) {
  extendObservable(this, {
    title: 'foo',
    rate: { pr: 30, desc: 'hoge' }
  }
}

// プリミティブなやつ
const num = observable(20);
// 代入しちゃうとアレなのでそれ用の手段で更新
num.set(30);

プリミティブだろうがオブジェクトだろうが、渡すと再帰的に面倒みてくれます。
ただ`prototype`をもってるやつは、`extendObservable()`で明示的にObservableにしたいプロパティを指定しないとダメです。

ObserverとなるReactコンポーネント

class Foo extends React.Component {}
module.exports = observer(Foo);

const Bar = () => {};
module.exports = observer(Bar);

SFCだろうがなんだろうが`observer()`で囲むだけ。

ちなみに、いかなる子コンポーネントであろうとも、Observableな値を表示するのであれば、`observer()`で囲みます。
その理由が知りたいならこのリンクを。

Do child components need `@observer`? · Issue #101 · mobxjs/mobx · GitHub

とりあえずコレだけで、後は全部MobXがいい感じにしてくれる!素敵!

というわけで

少なくともReduxよりも必要なボイラープレート的コードは少ないのは確かで、そこは優位性なのかなと思ってます。
ReactのViewにデータを配送することを考えると、もちろん自然とFlux(1方向データフローという意味で)的なコードを自分で書くようにはなるんやけど、それでも値を変更するだけでいい!そこだけ集中すればいい!というのは、コードの書き味としていいなと。
(もちろんいろいろ込み入ってくると覚えないといけないものは出てくるけど)

そもそもReduxと何が違うねん!とか、どういう用途に向いてる?とかは、そのままのIssueがあったのでコレを読むべし。

Understanding MobX and when to use it. · Issue #199 · mobxjs/mobx · GitHub


この記事は社内勉強会向けに使うスライド代わりなので短めです。
Part.2として書きたいネタもいくつかあるので、近いうちに書きまーす。