Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
49
Help us understand the problem. What is going on with this article?
@kimamula

TypeScript の JSX/React サポートを試す

More than 5 years have passed since last update.

1.5.0-beta には入っていません (2015/07/21 追記: 1.5.3 にも入っていません。 1.6 で入る模様) が、 TypeScript の master ブランチでは、 JSX/React がサポートされています。

React/Flux の TodoMVC のサンプルコードを、これを使って TypeScript 化してみました。

コードはこちらから見られます。

こちらのサイトの説明を参考にさせていただきました。

ポイント

  • JSX を書くときは拡張子を .tsx にする
  • component は React.Component<P, S> を extends したクラスを作成する
    • P は props の型、 S は state の型
    • React.createClass で作ると、クラス内での this の参照がうまく解決できないので避けたほうがよいと思われる
  • getInitialState() は、 React.createClass で作ったクラスでしか機能せず、上記の方法でクラスを作った場合は使えない
    • メソッドを定義するとコンソールに warning が出力され、実際 state が undefined になってしまう
    • constructor で初期化すれば OK (constructor の引数が props なので、 state の初期値が props に依存する場合でも対応可)
  • tsc のオプションの --jsx
    • preserve: jsx の記法のまま (<div/> -> <div/>)
    • react : react のメソッドを使った記法に変換される (<div/> -> React.createElement("div"))
    • サンプルコードでは、 JS 変換後に reactify とかするのが面倒だったので、 --jsx react しました

サンプル

一例として、 TodoTextInput.tsx のコードを貼っておきます。

/// <reference path="../../typings/tsd.d.ts" />
import * as React from 'react';

let ENTER_KEY_CODE = 13;

export interface Props {
    className?: string;
    id?: string;
    placeholder?: string;
    onSave: (value: string) => void;
    value?: string;
}

export default class TodoTextInput extends React.Component<Props, {value: string;}> {

    constructor(props: Props) {
        super(props);
        this.state = { 'value': props.value ? props.value : '' };
    }

    render(): JSX.Element  {
        return (
            <input
                className={this.props.className}
                id={this.props.id}
                placeholder={this.props.placeholder}
                onBlur={() => {
                    this.save();
                }}
                onChange={(event: React.FormEvent) => {
                    this.onChange(event);
                }}
                onKeyDown={(event: React.KeyboardEvent) => {
                    this.onKeyDown(event);
                }}
                value={this.state.value}
                autoFocus={true}
            />
        );
    }

    private save(): void {
        this.props.onSave(this.state.value);
        this.setState({ 'value': '' });
    }

    private onChange(event: React.FormEvent): void {
        this.setState({ 'value': event.target['value'] });
    }

    private onKeyDown(event: React.KeyboardEvent): void {
        if (event.keyCode === ENTER_KEY_CODE) {
            this.save();
        }
    }

}

ちなみに

単に TypeScript の JSX/React サポートを試すだけなら、 component だけ書いておけばよかったわけですが、なぜ Flux 一式書いてみたかというと、 ts-eventemitter という自作ライブラリを試してみたかったからです。

それについては別途記事を書く予定です。 -> 書きました TypeScript の機能で EventEmitter のイベントの payload を型安全に扱う

49
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
kimamula

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
49
Help us understand the problem. What is going on with this article?