J'ai des problèmes pour mettre à jour l'état dans un composant React que j'écris en TypeScript (React with Addons 0.13.3, TypeScript 1.6.0-dev.20150804, fichier de définition de 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;
Le code d'appel est
/// <reference path="react/react-addons.d.ts" />
import React = require("react/addons");
import App = require("app");
React.render(App({}), document.getElementById("jsapp"));
Le composant s'affiche comme prévu, mais les méthodes handleClick
et handleChange
ne mettent pas l'état à jour correctement. Si je mets des points d'arrêt dans ces deux méthodes et render
alors je vois les valeurs suivantes pour this
:
render
: this
est un objet Tester (ce que j'attendrais).handleChange
: this
est un ReactClass.createClass.Constructor
.handleClick
: this
est une référence à l'objet Window
.Les deux derniers signifient que l'objet d'état n'est pas disponible.
Toutes les suggestions reçues avec reconnaissance.
Vous devez changer votre méthode de rendu:
render() {
// ...
<button onClick={this.handleClick.bind(this)}>Like</button>
<input value={this.state.name} onChange={this.handleChange.bind(this)} />
// ...
}
Puisque vous appelez un événement, le mot-clé this
sera remplacé par le contexte par défaut de l'événement. En utilisant .bind(this)
vous vous assurez que le contexte appelé sera l'instance de votre classe.
Vous devez lier des méthodes avec this
car vous n'utilisez pas React.createClass
qui le fait automatiquement. Exemple avec une syntaxe de classe:
class Counter extends React.Component {
constructor() {
super();
this.handleChange = this.handleChange.bind(this);
this.handleClick = this.handleClick.bind(this);
}
handleChange() {
...
}
handleClick() {
...
}
}
Une autre méthode consiste à utiliser les fonctions de flèche grasse pour les gestionnaires d'événements qui obtiennent automatiquement "cette" liaison.
handleClick = (evt, domNode):void => {
this.setState({ liked: !this.state.liked, name: this.state.name });
};
<button onClick={() => this.handleClick()}>Like</button>