使用Typescript和JSX反应事件处理程序

Ian*_*n G 17 typescript reactjs react-jsx

我在使用TypeScript编写的React组件中更新状态时出现问题(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;
Run Code Online (Sandbox Code Playgroud)

调用代码是

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

React.render(App({}), document.getElementById("jsapp"));
Run Code Online (Sandbox Code Playgroud)

该组件呈现为我所期望的,但handleClickhandleChange方法不正确地更新状态.如果我在这两个方法中放置断点,render然后我看到以下值this:

  • render:this是一个Tester对象(我期望的).
  • handleChange:this是的ReactClass.createClass.Constructor.
  • handleClick:thisWindow对象的引用.

后两者意味着状态对象不可用.

任何建议都感激不尽.

sha*_*are 13

您必须绑定方法,this因为您React.createClass不会自动使用它.类语法示例:

class Counter extends React.Component {
  constructor() {
    super();
    this.handleChange = this.handleChange.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }
  handleChange() {
    ...
  }
  handleClick() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)


Buz*_*nas 10

您必须更改渲染方法:

render() {
    // ...
        <button onClick={this.handleClick.bind(this)}>Like</button>
        <input value={this.state.name} onChange={this.handleChange.bind(this)} />
    // ...
}
Run Code Online (Sandbox Code Playgroud)

由于您正在调用事件,因此this关键字将更改为事件的默认上下文.通过使用.bind(this)您确保被调用的上下文将是您的类的实例.

  • 请注意,虽然渲染中的绑定有效,但它确实会导致性能问题.https://medium.com/@esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#9bed (8认同)

Sam*_*ppe 10

另一种方法是对事件处理程序使用胖箭头函数,它们会自动"绑定".

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

 <button onClick={() => this.handleClick()}>Like</button>
Run Code Online (Sandbox Code Playgroud)