TypeScriptでReactを書く(1):JSX

More than 3 years have passed since last update.

TypeScriptでReactを書きたかったので雑にメモする。


TypeScriptでJSXのコンパイル

Reactはまあ出来るとして、JSXがちゃんとコンパイル出来るのか疑問だったがTypeScript1.6から出来るらしい。2015.8.15現在のバージョンは1.5系なのでnextバージョンをインストールする必要あり。グローバルのtscは別プロジェクトで現行系を使いたいのでlocal installにした。

$ npm install typescript@next --save

JSXをコンパイルするには拡張子を.tsxにする必要があるらしい。あとはコンパイル時に--jsx reactオプションが必要。

もろもろの事情によりタスクランナーはGruntを使っているため、自動コンパイルをしたかったのだが、grunt-typescriptだとどう設定しても.tsxの拡張子は対応してませんと怒られた(設定方法が悪かったのかもしれない)。

追記;grunt-typescript自体にtypescriptが入っていて、それのバージョンが調べた時点で1.5 betaだった。1.5は正式版が出てるので、gruntはgrunt-tsを使ったほうがいいのかもしれない。

一方grunt-tsなら次の設定でコンパイルが出来たのでこれを使うことにした。

  dev: {

src: [
'assets/scripts/ts/**/*.ts', 'assets/scripts/ts/**/*.tsx'
],
options: {
noImplicitAny: false,
module: 'umd',
removeComments: true,
additionalFlags: '--jsx react',
fast: 'never'
}
}

あとは型定義ファイルのインストールも忘れずに

$ dtsm init

$ dtsm install react --save

Reactのビルドのためにbrowserifyを入れたりもするんだけど、その辺りはTypeで書こうが何で書こうが同じなので割愛。


実装

Reactコンポーネントをどうやって書くの?というところで若干詰まった。よく考えるとTypeScriptはES6をしっかりと追っかけているのでES6の例をだいたいそのまま持ってきたら動く。

React0.13から(?)、creatClass()をしなくてもES6 classでReact.componentを継承するとコンポーネントが作れるようになった。この点はTypeScriptも同じ(ジェネリクスだけ付けてあげればOK)。

ポイントはconstructor()をしっかりと実装すること、super()を呼び出すことの2点。


Hello.tsx

/// <reference path="../../../typings/bundle.d.ts" />

import * as React from 'react';

class Hello extends React.Component<any, any> {

constructor(props) {
super(props);
this.state = {
count: 0
}
}

onClick() {
this.setState({ count: this.state.count + 1});
}

render() {
return (
<div>
<div>count, { this.state.count }</div>
<button onClick={ this.onClick.bind(this) }>UP!</button>
</div>
);
}
}

React.render(<Hello />, document.getElementById('app'));


あとはHTMLにタグを埋めたら表示される。


index.html

<div id="app"></div>


あと詰まったポイントはJSX内でthis.onClick.bind(this)としている所。これをついthis.oncClick()と書いてしまっていた。クラス内メソッドで定義されているonClick()なのでHelloにバインドされて呼び出されるかと思っていたら、そりゃDOMから直接(?)メソッドコールされるときはthis変わるよね、という話。