Typescript 1.6から React がサポートされました。
reduxが最近注目されているので、この機能を使用したいと思います。
以前は fluxxorを使用して React.js, Flux, CofeeScriptで試作したメモの記事を書きましたが、
Dispacherのあたりが冗長に感じていました。
reduxは、特に reducerがテストし易いので、大変良いと思います。
今回は、下記の様にライブラリを使用せず 機能を開発してみました。
- reduxの Store機能は、ReactのTop Componentのstateをそのまま使用する。
- Dispacherに複数のreducerを登録すると、stateが変わるまで順次処理される。
- Stateの取得、Dispachの容易さを考え、Top ComponentのインスタンスをGlobal変数に設定する。
- 具体的には今回の例では、$w.appがTop Component, $w.dispatcher がDispacherなど。
Herokuで実際に動く所が見れます。http://typeredux.herokuapp.com/
それでは ToDo アプリを見てみます。
Stateの初期値は下記の通りです。
main.tsx
state: any =
{
todoList:[],
newItem:{
description:""
}
};
例えば、inputの onChange イベントの処理は、name属性に、stateのPathを # 区切りで下記の様に指定します。
<input type="text" placeholder="input new item"
name="newItem#description"
value={this.state.newItem.description} onChange={$w.onChange} />
$w.onChangeは、下記のCodeです。
common.ts
$w.onChange = (e: any) => {
var action =cmn_set_value(
e.target.name.split("#"),
e.target.value)
$w.dispatcher.dispatch(action)
}
action の cmn_set_valueは、
common.ts
export function cmn_set_value(keys:string[],value:any):any{
var action = {
type: CMN_SET_VALUE,
keys: keys,
value: value
}
return action;
}
reducerのSample
common.ts
export function CMN_Reducer(state: any, action: any) {
switch (action.type) {
case CMN_SET_VALUE:
return Immutable.fromJS(state).updateIn(
action.keys, (value) => action.value).toJS()
default:
return state;
}
}
dispatcherは
common.ts
export class Dispatcher {
reducers: any;
constructor(reducers) {
this.reducers = reducers;
}
dispatch(action: any) {
var state = $w.app.state;
for (var no in this.reducers) {
var newState = this.reducers[no](state, action);
if (state !== newState) {
$w.app.setState(newState);
return;
}
}
return;
}
}
ソースコードは、https://github.com/mikeshimura/typereduxで見られます。