javascript - React this.setState er ikke en funksjon
Får stadig denne feilen når jeg prøver å skrive en app som fungerer med en tredjeparts API
TypeError: this.setState er ikke en funksjon
når jeg prøver å håndtere API-responsen. Jeg mistenker at det er noe galt med denne bindingen, men jeg kan ikke finne ut hvordan jeg kan fikse det. Her er koden til komponenten min:
var AppMain = React.createClass({
getInitialState: function() {
return{
FirstName: " "
};
},
componentDidMount:function(){
VK.init(function(){
console.info("API initialisation successful");
VK.api('users.get',{fields: 'photo_50'},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
});
}, function(){
console.info("API initialisation failed");
}, '5.34');
},
render:function(){
return (
<div className="appMain">
<Header />
</div>
);
}
});
Svar #1
Tilbakekallet gjøres i en annen kontekst. Du må bind til this for å ha tilgang inne i tilbakekallet:
VK.api('users.get',{fields: 'photo_50'},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
}.bind(this));
REDIGER: Ser ut som du må binde både init og api-kallene:
VK.init(function(){
console.info("API initialisation successful");
VK.api('users.get',{fields: 'photo_50'},function(data){
if(data.response){
this.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(this.state.FirstName);
}
}.bind(this));
}.bind(this), function(){
console.info("API initialisation failed");
}, '5.34');
Svar #2
Du kan unngå behovet for .bind(this) med en ES6 pilfunksjon.
VK.api("users.get", { fields: "photo_50" }, (data) => {
if (data.response) {
this.setState({
//the error happens here
FirstName: data.response[0].first_name,
});
console.info(this.state.FirstName);
}
});
Svar #3
React anbefaler å binde this i alle metoder som trenger å bruke this av class i stedet for this av selv function.
constructor(props) {
super(props)
this.onClick = this.onClick.bind(this)
}
onClick () {
this.setState({...})
}
Eller du kan bruke arrow function i stedet.
Svar #4
du kan også lagre en referanse til this før du kaller api-metoden:
componentDidMount:function(){
var that = this;
VK.init(function(){
console.info("API initialisation successful");
VK.api('users.get',{fields: 'photo_50'},function(data){
if(data.response){
that.setState({ //the error happens here
FirstName: data.response[0].first_name
});
console.info(that.state.FirstName);
}
});
}, function(){
console.info("API initialisation failed");
}, '5.34');
},
Svar #5
Du trenger bare å koble til hendelsen din
for eks-
// place this code to your constructor
this._handleDelete = this._handleDelete.bind(this);
// and your setState function will work perfectly
_handleDelete(id){
this.state.list.splice(id, 1);
this.setState({ list: this.state.list });
// this.setState({list: list});
}
Svar #6
bruk pilfunksjoner, siden pilfunksjoner peker til foreldreomfang og this vil være tilgjengelig. (erstatning for bind-teknikken)
Svar #7
Nå som ES6 har pilfunksjoner, er det veldig nyttig hvis du virkelig er forvirret over bind(this)-uttrykket; du kan prøve pilfunksjon.
Slik gjør jeg.
componentWillMount() {
ListApi.getList()
.then(JsonList => this.setState({ List: JsonList }));
}
//Above method equalent to this...
componentWillMount() {
ListApi.getList()
.then(function (JsonList) {
this.setState({ List: JsonList });
}.bind(this));
}
