出ました。
目玉機能!みたいなのはないです。
それだけ安定してるという意味でもある。
decorate() から makeObservable() へ
APIにおける一番の変更がコレ。
v4とv5では、いわゆるStoreはこんな風に作ってた。
import { decorate, observable } from 'mobx'; class FooStore { foo = 'text'; shallowObj = {}; shallowArr = []; } decorate(FooStore, { foo: observable, shallowObj: observable.shallow, shallowArr: observable.shallow, });
`class`を作ったあとで、`decorate()`という関数でもってObservableにする。
この`decorate()`が廃止されて、代わりに`makeObservable()`と`makeAutoObservable()`という関数に。
import { makeObservable, observable } from 'mobx'; class FooStore { foo = 'text'; shallowObj = {}; shallowArr = []; constructor() { makeObservable(this, { foo: observable, shallowObj: observable.shallow, shallowArr: observable.shallow, }); } }
まあそのまんまですね。
`observable.shallow`とか、`observable.ref`とかを使わないなら、`makeAutoObservable(this)`だけでもよいです。
`computed`や`action`なども、全部自分で明示するなら`makeObservable()`で。
TypeScriptの場合はこうしないと型エラーになるので注意。
import { makeObservable, observable } from 'mobx'; class FooStore { foo = 'text'; shallowObj = {}; shallowArr = []; constructor() { makeObservable<FooStore>(this, { foo: observable, shallowObj: observable.shallow, shallowArr: observable.shallow, }); } }
ドキュメントが一新された
正直いままでのドキュメントは、お世辞にもわかりやすいとは言えませんでした。
新規でMobXに興味をもった人も、離脱するんじゃねーかってくらいに・・。
しかしそれも!今回で!!
というわけで、めちゃくちゃ読みやすくなったので、ぜひ読んでください。
MobX x React
MobXユーザーはだいたいReactユーザーだと思うので、そっちも触れておく。
古いコードベースじゃない限りは、`mobx-react`ではなく、`mobx-react-lite`というパッケージを使ってください。
で、今回のアップデートではAPIの追加というよりも、DepricatedになったAPIのほうが多いです。
なんならこのパッケージからは4つのAPIしか利用を推奨しません。
- `observer()` HoC
- `Observer` コンポーネント
- `useLocalObservable()` フック
- `enableStaticRendering()`
これだけ。
コンポーネントで使う
コンポーネントをReactiveにするための方法が、いままでは3つあったんですが、それが2つになります。
- `observer()` HoC
- `Observer` コンポーネント
この2つのどっちかを使う。
前者は、Functionコンポーネントに対してのみ使えて、後者はどちらの中でも使えます。(正確には、`mobx-react`パッケージの`observer()`は、Classコンポーネントにも使えるけど)
個人的には、HoCより、再描画させたい範囲を明示的に区切るために`Observer`を使いたい派です。
コンポーネント内で、Observableな値をつくる
`useState()`があるのでそこまで活躍の機会はないけど。
直接`mobx`パッケージから`observable()`を持ってきてもいいけど、フックでそれを定義できるというのが`useLocalObservable()`です。
ドキュメントにも書いてあるけど、ただのショートハンド。
const [state] = useState(() => observable(initializer(), annotations, { autoBind: true }))