Обработать обработчики событий с помощью 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
не будут корректно обновлять состояние. Если бы я поставил точки останова в этих двух методах и render
, то я вижу следующие значения для this
:
-
render
: this
- объект тестера (чего бы я ожидал).
-
handleChange
: this
является ReactClass.createClass.Constructor
.
-
handleClick
: this
является ссылкой на объект Window
.
Последние два означают, что объект состояния недоступен.
Любые предложения с благодарностью получены.
Ответы
Ответ 1
Вы должны изменить метод рендеринга:
render() {
// ...
<button onClick={this.handleClick.bind(this)}>Like</button>
<input value={this.state.name} onChange={this.handleChange.bind(this)} />
// ...
}
Поскольку вы вызываете событие, ключевое слово this
будет изменено на контекст по умолчанию для события.
Используя .bind(this)
, вы убедитесь, что вызываемый контекст будет экземпляром вашего класса.
Ответ 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
Другим методом является использование функций стрелочной стрелки для обработчиков событий, которые получают автоматическую привязку "this".
handleClick = (evt, domNode):void => {
this.setState({ liked: !this.state.liked, name: this.state.name });
};
<button onClick={() => this.handleClick()}>Like</button>