Edited at

React + TypeScript + MobXで簡易Counterアプリで素振りを行った


  • ほぼ参考にしました

sample-react-mobx


プロジェクト作成

今回はTypeScriptを利用するので,optionをつけてアプリを作成します

create-react-app --scripts-version=react-scripts-ts [app_name]


mobxをインストール

npm install --save mobx mobx-react


いじっていく

まずApp.tsxを以下のように変更します.


App.tsx

import React, { Component } from 'react';

import CountContainer from './containers/CountContainer';

class App extends Component {
render() {
return (
<CountContainer />
);
}
}

export default App;


今回,stateをもらってくる役目をCountContainerにしてもらいました.

(reduxっぽい感じにしたかった・・・)


必要なディレクトリを作成

mkdir containers

mkdir components
mkdir stores

storeはデータの置き場みたいなもので,このstoreのメソッドを呼び出すことによってデータを変更していきます.


CountContainer


./containers/CountContainer.tsx

import React, { Component } from 'react';

import { Provider } from 'mobx-react';
import CountStore from '../store/CountStore';
import Counter from '../components/Counter';

// create store
const stores = new CountStore();

export default class CountContainer extends Component {
render() {
return (
<Provider count={stores}>
<Counter />
</Provider>
);
}
}



Counter


./components/Counter.tsx

import React, { Component } from 'react';

import { inject, observer } from 'mobx-react';
import { CountStoreType } from '../store/CountStore';

type Props = {
count?: CountStoreType
};

@inject('count')
@observer
class Counter extends Component<Props> {
render() {
const { count } = this.props;

return (
<div>
Counter : {count!.num} <br />
< button onClick={count!.onIncrement} > + </button>
< button onClick={count!.onDecrement} > - </button>
< br /> GetDoubleCount: {count!.getDoubleCount}
</div>
);
}
}

export default Counter;



CountStore

Typeを無理やり作ってますが,こんな感じの定義で


./store/CountStore.ts

import { observable, action, computed } from 'mobx';

export type CountStoreType = {
num: number
getDoubleCount: () => void
onIncrement: () => void
onDecrement: () => void
};

export default class CountStore {
@observable num = 0;

@computed get getDoubleCount() {
return this.num * 2;
}

@action.bound onIncrement() {
this.num = this.num + 1;
}

@action.bound onDecrement() {
this.num = this.num - 1;
}
}


あとはyarn startで動くと思います.


詰まった点


import fails with 'no default export'

tsconfig.json"compilerOptions"の中に以下を記述します.

"allowSyntheticDefaultImports": true


Providerで値を渡す

このブログに書かれているようにProviderからもらってくる値には?を付ける必要があります.


アノテーション周り

"experimentalDecorators": true,

これをtsconfig.jsonに書くとエラーが消えました.


まとめ

今回はMobX, TypeScriptの素振りがしたくて少し触ってみました.コードを組んでいく方向性としてcontainerを用意しましたが,componentとstoreだけで結構十分かなぁと思ったりもしました.🤔そこは規模感だったりいろいろと考えていきたいです.😊