【问题标题】:React event handlers with Typescript and JSX使用 Typescript 和 JSX 反应事件处理程序
【发布时间】:2015-11-05 09:18:00
【问题描述】:

我在使用 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;

调用代码是

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

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

组件按照我的预期呈现,但 handleClick 和 handleChange 方法不能正确更新状态。如果我在这两种方法和render 中设置断点,那么我会看到this 的以下值:

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

后两者表示状态对象不可用。

任何建议都非常感谢。

【问题讨论】:

    标签: typescript reactjs react-jsx


    【解决方案1】:

    另一种方法是对事件处理程序使用胖箭头函数,它会自动绑定“this”。

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

    【讨论】:

    • Lambda 在 JSX 属性中被禁止使用,因为它们会影响渲染性能
    • 另一篇文章直接反驳说它们会导致渲染问题。我也一直很好奇这个。 stackoverflow.com/questions/43968779/…
    【解决方案2】:

    您必须使用this 绑定方法,因为您不使用自动执行此操作的React.createClass。 类语法示例:

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

    【讨论】:

      【解决方案3】:

      你必须改变你的渲染方法:

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

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

      【讨论】:

      • 请注意,虽然在渲染中绑定有效,但它确实会导致性能问题。 medium.com/@esamatti/…
      • @CraigWalker 很好的阅读材料。事实上,我通常使用带有箭头函数的类属性来创建我的绑定函数,但你完全正确地谈论这个答案中给出的例子! :)
      • 你不应该在render方法中绑定,绑定应该在构造函数中完成,render中的绑定会在每次渲染时创建一个新函数。
      猜你喜欢
      • 1970-01-01
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      相关资源
      最近更新 更多