72
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MobXでReactのステート管理をする

Last updated at Posted at 2016-06-23

MobXはSimple, scalable state management を謳うステート管理マネージャ。

最近Hacker NewsやEchoJSで、にわかにMobXがフィーチャーされている。

3 Reasons why I stopped using React.setState — Medium

この記事を読んで、そんなにいいもんかなと思い、試してみることにした。

mobxjs/mobx: Simple, scalable state management.

カウンター

簡単なカウンターを作ってみる。一秒で1インクリメンタルされるやつ。

import ReactDOM from "react-dom";
import React from "react";
import {observable} from "mobx";
import {observer} from 'mobx-react'

class AppState {
  id = Math.random();
  @observable counter = 0;
}

@observer
class App extends React.Component {
  render() {
    return <div className="app">{this.props.data.counter}</div>
  }
}

const el = document.querySelector(".main");
const appState = new AppState();
ReactDOM.render(<App data={appState} />, el);

setInterval(() => {
  appState.counter += 1;
}, 1000);

ステート側のリアクティブにしたいプロパティにmobx の@observable デコレーターを付け、Reactのコンポーネント側にmobx-react の @observer デコレーターを付与する。

あとはステート側を書き換えると変更が反映される。たぶんobserver ついたComponentのコンストラクタで observervable なプロパティの変更をフックして、高階コンポーネントのsetStateを呼び出してそう。(中身読んでないけど自分ならそう作るだろうなという予想)

Vueのデータバインダを思い出す感じもある。

@computed

他の値に依存する値を表現する

class AppState {
  @observable counter = 0;

  constructor(counter) {
    this.counter = counter;
  }

  @computed get twice() {
    return this.counter * 2;
  }
}

@observer
class App extends React.Component {
  render() {
    return <div className="app">{this.props.data.twice}</div>
  }
}

これで2倍表示されるようになった。

Becoming fully reactive: an in-depth explanation of MobX — Medium

@action

setState と違って値を1つずつ更新するため、非同期で複数更新すると、無駄にrenderが走ることになる。それを抑制するのがactionデコレータ。

class AppState {
  @observable counter;

  constructor() {
    this.counter = 0;
  }

  @computed get twice() {
    return this.counter * 2;
  }

  @action
  incrementLazy() {
    this.counter -= 1;
    setTimeout(() => {
      this.counter += 2;
    }, 100);
  }
}

@observer
class App extends React.Component {
  render() {
    return <div className="app">{this.props.data.twice}</div>
  }
}

たとえばactionデコレータ を外すとこのような振る舞いになる。

デコレータがついてる場合は-1した部分がスキップされる。

(トランザクションの終了検知を実装するには、関数内部の静的解析が必要な気がするが、どうなってるんだろう?)

感想

デコレータでリアクティブプロパティーを作る部分は面白いが、入れ子のプロパティーを作ろうとするとasStructureという専用の構築子を要求されたりしだして、だるい感じ。正直トランザクション管理も自分でつくりだした沼にハマってるだけなので、別にsetStateでいい。

サンプルコード読んだり中身を想像する分には面白かった。

参考

tonyspiro/easy-mobx-example: Easy MobX + React Example https://github.com/tonyspiro/easy-mobx-example

MobX: Ten minute introduction to MobX and React

72
62
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
72
62

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?