2015-06-25 15 views
109

Jestem nowy w React i próbuję napisać aplikację działającą z interfejsem API. Ciągle otrzymuję ten błąd: TypeError: this.setState nie jest funkcją kiedy próbuję obsłużyć odpowiedź API. Podejrzewam, że coś jest nie tak z tym wiązaniem, ale nie mogę wymyślić, jak to naprawić. Oto kod mojego komponentu:React this.setState nie jest funkcją

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> 
     ); 
    } 
}); 

Odpowiedz

158

Wywołanie zwrotne jest wykonany w innym kontekście. Trzeba bind do this w celu uzyskania dostępu do wnętrza callback:

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)); 

EDIT: Wygląda na to trzeba wiązać zarówno init i api połączenia:

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'); 
+0

Pokaż to jest w tutorialu: http://facebook.github.io/react/docs/tutorial.html –

29

można również zapisać odniesienie do this przed wywołać metodę api:

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'); 
}, 
61

Możesz uniknąć potrzeby .bind (this) za pomocą funkcji strzałki ES6.

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); 
     } 

    }); 
+0

Działa to dobrze. W rzeczywistości słowo kluczowe funkcji nie powinno być wyświetlane w pliku es6. –

+4

Twoja odpowiedź pomogła mi :-) Używając klasy ES6 i RN 0.34, znalazłem dwa sposoby powiązania "tego" z funkcją wywołania zwrotnego. 1) 'onChange = {(checked) => this.toggleCheckbox()}', 2) 'onChange = {this.toggleCheckbox.bind (this)}'. – devdanke

+0

może pomóc wyjaśnić, jak to działa? – GMsoF

2

Teraz ES6 mieć funkcja to strzałka naprawdę pomocne, jeśli naprawdę mylić z bind (this) wyrażenie można spróbować funkcji strzałki

To jak ja.

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)); 
}