2014-11-27 31 views
17

Próbuję ReactJS, ale mam trudności z włączeniem go do mojej postaci. W ReactJS buduję formularz autosugestii. W moim onChangeQuery ustawiam stan, a następnie wywołuję funkcję AJAX, aby pobrać sugestie z mojego kodu po stronie serwera; Zauważyłem jednak, że funkcja loadGroupsFromServer nie otrzymuje ostatniego stanu ... To jedno naciśnięcie klawisza zbyt wolne. Wiem, że setState nie jest natychmiastowy, ale dlaczego miałbym kiedykolwiek używać setState do moich formularzy? Czy lepiej stosować refs? Lepiej zdobyć wartość z e.target.value?ReactJS setState jest powolny

Pomoc!

var GroupForm = React.createClass({ 
    getInitialState: function() { 
     return {query: "", groups: []} 
    }, 
    componentDidMount: function() { 
     this.loadGroupsFromServer(); 
    }, 
    loadGroupsFromServer: function() { 
     $.ajax({ 
     type: "GET", 
     url: this.props.url, 
     data: {q: this.state.query}, 
     dataType: 'json', 
     success: function (groups) { 
      this.setState({groups: groups}); 
     }.bind(this), 
     error: function (xhr, status, err) { 
      console.error(this.props.url, status, err.toString()); 
     }.bind(this) 
     }); 
    }, 
    onChangeQuery: function(e) { 
     this.setState({query: e.target.value}) 
     this.loadGroupsFromServer(); 
    }, 
    render: function() { 
     return (
     <div> 
      <form class="form form-horizontal"> 
      <div class="col-lg-12"> 
       <input type="text" className="form-control" value={this.state.query} placeholder="Search for groups" onChange={this.onChangeQuery} /> 
      </div> 
      </form> 
      <GroupList groups={this.state.groups} /> 
     </div> 
    ) 
    } 
    }) 
+0

jeśli wywołasz setState samodzielnie, nie powinieneś oczekiwać, że to .state zostanie natychmiast zaktualizowane. –

Odpowiedz

5

loadGroupsFromServer powinien pobrać argument zapytania.

componentDidMount: function() { 
    this.loadGroupsFromServer(this.state.query); 
}, 
loadGroupsFromServer: function (query) { 
    $.ajax({ 
    /* ... */ 
    data: {q: query}, 
    /* ... */ 
    }); 
}, 
onChangeQuery: function(e) { 
    this.setState({query: e.target.value}) 
    this.loadGroupsFromServer(e.target.value); 
}, 

Należy generalnie starają się ograniczyć dostęp do stanu, bo to daje większą elastyczność.

zależności od przypadku może chcesz czekać na składniku zaktualizować przed wykonaniem jakiegoś działania:

onChangeQuery: function(e) { 
    this.setState({query: e.target.value}, function(){ 
     this.loadGroupsFromServer(this.state.query) 
    }.bind(this)); 
}, 

Albo można przerobić go tak jak to, co jest moim zdaniem czystsze.

onChangeQuery: function(e) { 
    this.setState({query: e.target.value}); 
}, 
componentWillUpdate: function(nextProps, nextState){ 
    // optionally perform better heuristics, but this prevents them pressing space 
    // from triggering an update 
    if (nextState.query.trim() !== this.state.query.trim()) { 
     this.loadGroupsFromServer(nextState.query); 
    } 
} 
36

setState wykonuje wywołania zwrotnego, który pozwala zapewnić this.loadGroupsFromQuery() nazywa dopiero po this.state jest aktualizowana.

this.setState({...}, function() { 
    this.loadGroupsFromQuery(); 
}); 
3

Podstawową przyczyną problemu związanego z jednym bohaterem było to, że odczytywałeś stan przed jego ustawieniem. setState jest szybki, ale nie jest natychmiastowy i synchroniczny. Poprzednie odpowiedzi zapewniają kilka sposobów na refaktoryzację.

6

setstate Best Practice

ES5

this.setState(function(state){ 
    state.query= e.target.value; 
}, function()=>{ 
    //after callback 
}); 

ES6

this.setState(state => { 
    state.query= e.target.value; 
},()=>{ 
    //after callback 
}); 
+0

bardzo dziękuję :) – Giang

0

setstate nie jest powolny, ale to jest asynchroniczne. Tak jak na powyższą odpowiedź, będzie działać synchronicznie, niezależnie od tego, gdzie ustawiony jest twój stan.

Zgodnie z najlepszą praktyką należy określić stan poza metodą renderowania.