Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

TypeScript JSX + ReactでReduxなカウンターアプリ

$
0
0

Reduxなカウンターアプリを作ってみました。 TypeScript JSXで。

感想としては、この規模だとFluxより楽な気がします。規模が大きくなるとどうなるのか未知数。FluxのChatサンプルでも書き直してみたらわかるかなぁ。

Counterの作成

まずはクラスがないと始まりません。データの入れ物のCounterクラスです。

exportclass Counter {
    constructor(public count: number) {}}

Actionの作成

続けてインクリメントとデクリメントのActionを作っていきましょう。 これはenum持っただけの簡単なものにしました。

exportenum ActionTypes {
    Increment,
    Decrement
}exportinterface Action {
    type: ActionTypes;
}exportfunction increment() {return{
        type: ActionTypes.Increment
    } as Action;
}exportfunction decrement() {return{
        type: ActionTypes.Decrement
    } as Action;
}

Reducerの作成

続けてReducerです。Actionを受け取ってCounterを変更して返します。

import * as Redux from 'redux';
import * as Models from './models';
import * as Actions from './actions';
import objectAssign = require('object-assign');

function counter(state = new Models.Counter(0), action: Actions.Action) {switch (action.type) {case Actions.ActionTypes.Increment:
            return objectAssign({}, state, { count: state.count + 1 } as Models.Counter);
        case Actions.ActionTypes.Decrement:
            return objectAssign({}, state, { count: state.count - 1 } as Models.Counter);
        default:
            return state;
    }}const counterApp = Redux.combineReducers({
    counter
});

exportdefault counterApp;

コンポーネントの作成

ここら辺からreact-reduxの範疇になってきます。reduxに設定するアプリのプロパティは、dispatchというプロパティと、各種ステートを持ちます。今回のカウンターアプリの場合はCounterクラスを持たせるといいでしょう。

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import * as Redux from 'redux';
import{Provider, connect} from 'react-redux';
import todoApp from './reducers';
import * as Actions from './actions';
import * as Models from './models';


interface AppProps extends React.Props<{}> {
    counter?: Models.Counter;
    dispatch?: Redux.Dispatch;
}class App extends React.Component<AppProps, {}> {
    render() {const{ dispatch, counter } = this.props;
        return (
            <div>
                <p>{counter.count}</p>
                <button onClick={() => dispatch(Actions.increment())}>Inc</button>
                <button onClick={() => dispatch(Actions.decrement())}>Dec</button>
            </div>
        );
    }}

アプリのステートをインターフェースとして定義しておきます。今回はcombineReducersでCounterを返すcounter関数を渡してるので、以下のような感じになります。 ここらへん、combineReducersとの同期を手動でとらないといけないのでいまいち感。

interface AppState {
    counter: Models.Counter;
}

そして、AppStateからAppPropsへ変換するselect関数を準備します。

function select(state: AppState): AppProps {return{
        counter: state.counter
    };
}

次に、このselect関数を使ってAppクラスをreact-reduxと繋ぎます。

const ReduxCounterApp = connect(select)(App);

そして、アプリのstateを作ります。

let store = Redux.createStore(todoApp);

最後に、ProviderというタグでAppをくるんだものをReactDOM.renderに渡します。(お約束)

ReactDOM.render(
    <Provider store={store}>
        <ReduxCounterApp />
    </Provider>,
    document.getElementById('content'));

実行して動作確認

ボタンを押してインクリメントデクリメントできるアプリが出来上がりました。

f:id:okazuki:20160109170042p:plain


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>