🧊

MobX 4.0.0 について

去年の末から地道に対応が進んでたのですが、ついに出ましたねー。

作者によるサマリー記事とあわせて公開されました↓

MobX 4: Better, simpler, faster, smaller – Michel Weststrate – Medium

ちゃんとv3からv4へのマイグレーションガイドもあります。

Migrating from mobx 3 to mobx 4 · mobxjs/mobx Wiki · GitHub

フルのChangeLogもあるよ!

mobx/CHANGELOG.md at master · mobxjs/mobx · GitHub

というわけで、手元のプロジェクトをアップデートしたのでその作業メモと、軽くアップデートのご紹介。

`decorate()`

`decorate()`という関数で、何をどうObservableにするか指定できるようになりました。

たとえばこの古いv3のコード。

import { extendObservable, observable } from 'mobx';

class FooStore {
  constructor() {
    extendObservable(this, {
      foo: 'text',
      shallowObj: observable.shallowObject({}),
      shallowArr: observable.shallowArray([]),
    });
  }
}

Decoratorsシンタックスは怪しいので使ってなくて、`extendObservable()`で値を持ってるStoreのクラス。
そして、`observable.shallowXxx()`というModifierを使って、自動的に再起でObservalbeにされるのを回避してたコード。

ただこの度`observable.shallowXxx()`がお亡くなりになられましたので、これをいくつかのパターンで書き直す必要があった。

`extendObservable()` w/ decorators param

まずこれ。

import { extendObservable, observable } from 'mobx';

class FooStore {
  constructor() {
    extendObservable(this, {
      foo: 'text',
      shallowObj: {},
      shallowArr: [],
    }, {
      shallowObj: observable.shallow,
      shallowArr: observable.shallow,
    });
  }
}

このように、第3引数に`observable()`の挙動を変える引数を渡して、後からDecorateするように。

`decorate()`

もしくは、新たに追加されたAPIである`decorate()`を使ったパターン。

import { decorate, observable } from 'mobx';

class FooStore {
  constructor() {
    this.foo = 'text';
    this.shallowObj = {};
    this.shallowArr = [];
  }
}

decorate(FooStore, {
  foo: observable,
  shallowObj: observable.shallow,
  shallowArr: observable.shallow,
});

このパターンの場合は、全てのプロパティを明示的に`observable`指定する必要があるのでそこだけ注意。(例でいう`foo`)

まあObservableにしたくない場合は何もしなくていいので、MobXを一部だけ適用するみたいなイメージで使えていいかも。まあ`extendObservable()`と記述場所が変わったくらいやんって感じではある。

まぁコードの見通し的にも、これがオススメかな?

flow

さっきのDecoratorには今までもあった`action`とかも指定できるけど、その中でさらに増えたやつがあって、それが`flow`。

一言でいうと、非同期でObservableな値を更新しようとするとコードが煩雑になるケースがあって、それを回避できる便利なやつ。

詳細はこの記事および記事内の動画が詳しいのでおすすめ。

MobX Async Actions | Leigh Halliday

まあただ、

  • Storeで非同期しない派
    • = 別のところで叩いて、Storeは値を抱えるだけにしてる
  • `action`使ってない派

の人には関係ないです。俺もめっきり`useStrict(true)`改め`configure({ enforceActions: true })`してません。

その他

ChangeLogからそれらしいのを・・と思ったけど、使ってない機能とか使わなさそうな機能しかなかったので、特にないかな・・。

それくらい、簡単に移行できるアップデートってことですよ!

というわけで

割と長らくMobXユーザーやってますが、そこまでマニアックなAPIは使わず最低限のものしか使ってないので、移行にはまったく手こずらなかったなーという感想でした。
ちなみに次のMobx 5.0.0では、裏側の実装がProxyになったりするらしいですよ。乞うご期待。

なんかあったらTwitterで教えてくださいー。