4
7

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.

TypeScriptでcreate-react-appを使う(ImmutableとかReduxとかいろいろ含む)

Last updated at Posted at 2017-03-16

create-react-appを使うとReactの雛形を作ってくれるがTypeScriptには対応していないし,当面対応する予定もない。しかしforkしてTypeScriptの対応をしてくれたcreate-react-app-typescriptがある。これを使ってJavaScriptで作ったアプリをTypeScriptに書き直した。調べるのに苦労したので作業メモもかねてImmutableやReduxなどなどを使うアプリのサンプルを説明する。

以下のものを使う。JavaScriptによるReactアプリ作成・TypeScriptなどの要素技術は理解しているものとする。

  • yarn
  • TypeScript-2.2.1
  • React
  • create-react-app
  • Immutable
  • Redux
  • material-ui

初期設定

$ yarn global add create-react-app
$ create-react-app demo-react-scripts-ts --scripts-version=react-scripts-ts

他に必要なものをインストール

$ yarn add immutable
$ yarn add material-ui @types/material-ui
$ yarn add redux
$ yarn add redux-actions @types/redux-actions
$ yarn add react-redux @types/react-redux
$ yarn add react-tap-event-plugin

App.tsxの開設

単純にボタンを押して数字を増やしたり減らしたりして表示する。

class Counter extends Record({counter: 0}) {
    counter: number;

    modify(diff: number) {
        return new Counter(this.set('counter', this.counter + diff));
    }
}

Immutableを使ってデータを保持するクラスを作成する。Record#setがMapに変わってしまうのでこういうやりかたになる。TypeScriptはJavaScriptより型がきちんとあっていいのだがimmutableなコレクションを使いにくい部分があるかなと思う。

interface AppProps {
    data: Counter;
    updateModel: (d: Counter) => void;
}

class App extends React.Component<AppProps, undefined> {

アプリのメインの記述。Component<any,any>としておけばなんでも通るがinterfaceを渡せばコンパイル時に変なpropsを書いてないかチェックできるようになる。2番目は`this.stateのinterfaceだがReduxを使うのでthis.stateを使うことはない。

    render() {
        return (
            <MuiThemeProvider>
                <div className="App">
                    <h1>{this.props.data.counter}</h1>
                    <FloatingActionButton onClick={() => this.props.updateModel(this.props.data.modify(1))}>
                        <ContentAdd/>
                    </FloatingActionButton>

FloatingActionButtononChangeの中身がモデルの更新作業となる。

                    <FloatingActionButton
                        secondary={true}
                        onClick={() => this.props.updateModel(this.props.data.modify(-1))}
                    >
                        <ContentRemove/>
                    </FloatingActionButton>
                </div>
            </MuiThemeProvider>
        );
    }
}

ここからReduxの記述になる。

const initialState = new Counter();

先程作ったモデルを初期値とする。

const updateModel = createAction<Counter>('UPDATE_MODEL');

redux-actionsで作るactionはモデルを更新するという一つだけで済む。実際のデータの更新はモデルクラスのメソッドを使う。

const reducer = handleActions<Counter>(
    {
        ['UPDATE_MODEL']: (state: Counter, action: Action<Counter>) => action.payload
    },
    initialState
);

更新作業も直感的な作業となる。

const store = createStore(reducer);

function mapStateToProps(state: Counter) {
    return {data: state};
}

function mapDispatchToProps(dispatch: Dispatch<Counter>) {
    return {
        updateModel: function (m: Counter) {
            dispatch(updateModel(m));
        }
    };

}

メソッドの型をきちんと入れなければならない。最初は型がわからなかった。

export default class RApp extends React.Component<undefined, undefined> {
    render() {
        const DApp = connect(mapStateToProps, mapDispatchToProps)(App);
        return (
            <Provider store={store}>
                <DApp />
            </Provider>);
    }
}

このようになる。

4
7
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
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?