いちおうContributorもやってるので、なにか質問等あれば、この後の懇親会でもTwitterとかでもお気軽に!
必要なものを自分で見て「選択」する力を試すということで・・(˘ω˘ )
state
)を管理するためのライブラリ3.1.16
Reactと相性がよいのであわせて使われることが多いけど、別に依存関係はないです。
海外では既にそれなりに、日本でも少しずつ認知されてきた感がある今日このごろ。
Actions
によりState
を変更する。
State
が変更されると、自動的にReactions
が発火する。(= Views
も更新される。view = f(state)
)
mobx.action
mobx.observable
, mobx.computed
mobx.reaction
, mobx.autorun
mobx-react.observer
他にもAPIは色々ありますが、最低限これだけ覚えれば十分です。
const { autorun, observable } = require('mobx');
// State
const state = observable({
count: 1,
});
// Reaction(Views)
autorun(() => {
console.log(`Count is ${state.count}!`); // Count is 1!
});
// Actions
function increment() { state.count++; }
function decrement() { state.count--; }
increment(); // Count is 2!
increment(); // Count is 3!
decrement(); // Count is 2!
State
を定義して、使用して、変更するだけ。これが全て。
State
が変更されると自動的にただのオブジェクトで管理するよりも圧倒的にわかりやすいです。
const { action, computed, observable } = require('mobx');
// ObservableなStateと、Stateを変更するAction
// Decoratorsは必須ではなくOptionalな選択肢
class Store {
@observable count = 1;
// ObservableなStateに更新があった時"だけ"、自動的に更新されるプロパティ
@computed get isOdd() {
return !!(this.count % 2);
}
@action increment() {
this.count++;
}
@action decrement() {
this.count--;
}
}
// ViewからStoreのActionを呼ぶための・View以外の用途にStoreを使う層
// 別にViewから直接Storeを叩いてもいいけど
function createEvent(store) {
return {
increment() {
store.increment();
},
decrement() {
store.decrement();
}
};
}
const React, { Component } = require('react');
const { observer } = require('mobx-react');
// ObservableなStateに更新があった時"だけ"、自動的にrenderされるコンポーネント
@observer
class View extends Component {
render() {
const { store, event } = this.props;
return (
<div>
<div>{store.count}</div>
<button onClick={event.increment}>+</button>
<button onClick={event.decrement}>-</button>
</div>
);
}
}
const ReactDOM = require('react-dom');
const { useStrict, reaction } = require('mobx');
// @acitonからしかStateが変更できないように
useStrict(true);
const store = new Store();
// Stateの用途1
// ObservableなStateに更新があった時"だけ"、自動的に呼ばれる関数
reaction(
() => store.isOdd,
isOdd => {
console.log(isOdd ? 'odd' : 'even');
}
);
// Stateの用途2
ReactDOM.render(
<View store={store} event={createEvent(store)} />,
document.getElementById('app')
);
MobX自身はアーキテクチャは規定しないので、Fluxぽくするもよし、MVCぽくするもよし、MVVMぽくするもよし。
State
をどう定義するかが最大の関心事になるState
を用途に応じてリンクさせていくState
を更新すれば、「変更が必要なものだけ」が自動的にアップデートされるshouldComponentUpdate
的なチューニングも不要になるつまりState
を更新するだけで、
そんな思想を体現したDEMOのご紹介。
トーク自体もおもしろいのでおすすめです。
やや作者のクセが感じられると個人的には思ってたりする・・(˘ω˘ )
ReactDOM.render()
をソースから消してみた状態でも動く// Viewですら副作用であり必須ではない
shop.cart.checkout()
shop.cart.clear()
// URLでさえも
shop.view.openCartPage()
shop.view.openBooksPage()
// 全ての機能が動く
shop.books.keys()
shop.cart.addBook(shop.books.get('978-1423103349'))
shop.cart.addBook(shop.books.get('978-1423103349'), 2, false)
shop.cart.checkout()
https://github.com/mweststrate/react-mobx-shop/blob/react-amsterdam-2017/src/index.js#L13-L40
State
の更新によって反映されるべきものを紐付けReact
を使った画面表示State
を更新すればすべて自動で反映Store
を用意してまとめるBackbone
のModel
とCollection
の関係のようなhttps://github.com/mweststrate/react-mobx-shop/blob/react-amsterdam-2017/src/stores/ViewStore.js
https://github.com/mweststrate/react-mobx-shop/blob/react-amsterdam-2017/src/index.js#L17-L22 https://github.com/mweststrate/react-mobx-shop/blob/react-amsterdam-2017/src/components/Books.js#L4
Provider
でContextに注入してinject()
で取り出せるobserver()
は、そのコンポーネントが使用している値に更新があった時のみrender()
してくれるこの2つの仕組みを備えたライブラリです。
ちゃんと自分の目で見て試して「選択」してください・・・!
需要があれば、またの機会にどこかで!