web-dev-qa-db-ja.com

React TypeScriptおよびJSXのイベントハンドラー

React TypeScript(React with Addons 0.13.3、TypeScript 1.6.0-dev.20150804、定義ファイル http://definitelytyped.org/ )。

/// <reference path="react/react-addons.d.ts" />
import React = require("react/addons");

interface AppState {
}

interface TestState {
    liked: boolean,
    name: string
}

class Tester extends React.Component<any, TestState> {
    constructor(props) {
        super(props);
        this.state = { liked: false, name: "Anders" };
    }

    handleClick(evt, domNode): void {
        this.setState({ liked: !this.state.liked, name: this.state.name });
    }

    handleChange(evt, a, b, c): void {
        this.setState({ liked: this.state.liked, name: evt.target.value });
    }

    render() {
        var text = this.state.liked ? "liked " : "haven't liked "
        return (<div>You {text} {this.state.name} 
            <button onClick={this.handleClick}>Like</button>
            <input value={this.state.name} onChange={this.handleChange} />
        </div>);
    }
}

class App extends React.Component<{}, AppState> {
    constructor(props) {
        super(props);
    }

    render() {
        return (<div>
            <Tester />
        </div>);
    }
}

function Factory(props: {}) {
  return React.createElement(App, props);
}

export = Factory;

呼び出しコードは

/// <reference path="react/react-addons.d.ts" />
import React = require("react/addons");
import App = require("app");

React.render(App({}), document.getElementById("jsapp"));

コンポーネントは予想どおりにレンダリングされますが、handleClickおよびhandleChangeメソッドは状態を正しく更新しません。これらの2つのメソッドとrenderにブレークポイントを配置すると、thisに次の値が表示されます。

  • renderthisはTesterオブジェクトです(予想どおり)。
  • handleChangethisReactClass.createClass.Constructor
  • handleClickthisWindowオブジェクトへの参照です。

後者の2つは、状態オブジェクトが利用できないことを意味します。

感謝の気持ちで受け取った提案。

17
Ian G

レンダリング方法を変更する必要があります。

_render() {
    // ...
        <button onClick={this.handleClick.bind(this)}>Like</button>
        <input value={this.state.name} onChange={this.handleChange.bind(this)} />
    // ...
}
_

イベントを呼び出しているため、thisキーワードはイベントのデフォルトコンテキストに変更されます。 .bind(this)を使用することにより、呼び出されるコンテキストがクラスのインスタンスになるようにします。

10
Buzinas

メソッドを自動的に行うReact.createClassを使用しないため、thisでメソッドをバインドする必要があります。クラス構文の例:

class Counter extends React.Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleChange() {
    ...
  }
  handleClick() {
    ...
  }
}
13
shadeglare

別の方法は、自動「this」バインディングを取得するイベントハンドラに太い矢印関数を使用することです。

 handleClick = (evt, domNode):void => {
     this.setState({ liked: !this.state.liked, name: this.state.name });
 };

 <button onClick={() => this.handleClick()}>Like</button>
10
Sam Sippe